Onclicklistner не работает в представлении списка фрагментов

У меня есть список с пользовательским адаптером в listfragment, а также установлен onclicklistner для просмотра списка. Но Onclicklistner не работает.

Вот мой код:

public class BasicFragment extends ListFragment {

ListView lv;
MyCustomAdapter adapter;

@Override
public void onCreate(Bundle si) {
    super.onCreate(si);
}

@Override
public void onActivityCreated(Bundle b) {
    super.onActivityCreated(b);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_basic, container, false);
    lv = (ListView) view.findViewById(android.R.id.list);
    FetchedData DT = FetchedData.StaticDataTransfer();
    RecepiesProperties[] AryObjaz = DT.getData();
    getdata(AryObjaz);
    adapter = new MyCustomAdapter(getActivity(), R.layout.listview_layout,
            Dataset);
    lv.setAdapter(adapter);

    lv.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            Toast t = Toast.makeText(getActivity(), "Message",
                    Toast.LENGTH_SHORT);
            t.show();
        }
    });

    return view;
}}

MyCustomAdapter.java

public class MyCustomAdapter extends ArrayAdapter<Recipes> {

Context context;
int layoutResourceId;
Recipes data[] = null;
Typeface typeface;
public ImageLoader imageLoader;

public MyCustomAdapter(Context context, int textViewResourceId,
        Recipes[] dataset) {
    super(context, textViewResourceId, dataset);
    this.layoutResourceId = textViewResourceId;
    this.context = context;
    this.data = dataset;
    imageLoader = new ImageLoader(context.getApplicationContext());
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;

    LayoutInflater inflater = ((Activity) context).getLayoutInflater();
    row = inflater.inflate(layoutResourceId, parent, false);
    RecipesHolder holder = new RecipesHolder();
    holder.imgIcon = (ImageView) row.findViewById(R.id.imageView1);
    holder.txtTitle = (TextView) row.findViewById(R.id.title);
    holder.category = (TextView) row.findViewById(R.id.category);
    holder.source = (TextView) row.findViewById(R.id.source);
    holder.country = (TextView) row.findViewById(R.id.country);
    holder.readytime = (TextView) row.findViewById(R.id.readytime);
    holder.tips = (Button) row.findViewById(R.id.tips);
    holder.fav = (Button) row.findViewById(R.id.fav);

    Recipes ap = data[position];

    imageLoader.DisplayImage(ap.getIMAGENAME240(), holder.imgIcon);
    holder.txtTitle.setText(ap.getNAME());
    holder.category.setText(ap.getCATEGORY());
    holder.source.setText(ap.getSOURCE());
    holder.country.setText(ap.getCOUNTRY());
    holder.readytime.setText(ap.getREADYTIME());

    return row;
}

static class RecipesHolder {
    ImageView imgIcon;
    TextView txtTitle;
    TextView category;
    TextView source;
    TextView country;
    TextView readytime;
    Button tips;
    Button fav;
}}

//listview_layout.xml

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"><ImageView
    android:id="@+id/imageView1"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_alignParentLeft="true"
    android:focusable="true"
    android:layout_alignParentTop="true"
    android:layout_marginLeft="5dp"
    android:layout_marginTop="10dp" />

<TextView
    android:id="@+id/readytime"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBaseline="@+id/country"
    android:layout_alignBottom="@+id/country"
    android:layout_marginLeft="73dp"
    android:layout_toRightOf="@+id/country"
    android:focusable="true"
    android:text="TextView"
    android:textColor="#000" />

<TextView
    android:id="@+id/country"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/imageView1"
    android:layout_alignLeft="@+id/source"
    android:focusable="true"
    android:text="TextView"
    android:textColor="#000" />

<TextView
    android:id="@+id/source"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@+id/country"
    android:layout_alignLeft="@+id/category"
    android:focusable="true"
    android:text="TextView"
    android:textColor="#000" />

<TextView
    android:id="@+id/category"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@+id/source"
    android:layout_alignLeft="@+id/title"
    android:text="TextView"
    android:focusable="true"
    android:textColor="#000" />

<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@+id/category"
    android:layout_toRightOf="@+id/imageView1"
    android:text="TextView"
    android:focusable="true"
    android:textColor="#000" />

<Button
    android:id="@+id/fav"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/tips"
    android:layout_below="@+id/source"
    android:focusable="true"
    android:background="@drawable/favourite" />

<Button
    android:id="@+id/tips"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_alignTop="@+id/textView1"
    android:layout_marginRight="14dp"
    android:background="@drawable/yellow" /></RelativeLayout>

person jeevamuthu    schedule 27.02.2013    source источник
comment
Вы пытались объявить слушателя внутри onViewCreated(View view, Bundle saveInstanceState)? А не внутри onCreateView(). Он не должен жить в этом методе onViewCreate().   -  person Tool    schedule 27.02.2013


Ответы (9)


наконец-то решена проблема, когда все элементы управления (кнопки, текстовые представления) в списке установлены на фокусируемое значение false.

person jeevamuthu    schedule 05.03.2013
comment
Спасибо! Это помогло мне после часа отладки...! - person Mario Fraiß; 27.05.2013
comment
Это сработало и для меня! Я использую код android:focusable=false для всех Buttons и TextViews внутри моего XML, связанного с моим классом фрагмента. - person ymerdrengene; 19.05.2014

Проверьте свой MyCustomAdapter. Некоторые виджеты (такие как: Button, ImageButton) в пользовательском макете будут использовать событие щелчка, а затем onItemClick никогда не будет вызываться.

Используйте следующий код в методе getView вашего адаптера, чтобы получить событие onClick.

     row.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

        }
    });
person Bolton    schedule 27.02.2013

Согласно документу Android API:

ListFragment имеет макет по умолчанию, состоящий из одного представления списка. Однако при желании вы можете настроить макет фрагмента, вернув собственную иерархию представлений из onCreateView(LayoutInflater, ViewGroup, Bundle). Для этого ваша иерархия представлений должна содержать объект ListView с идентификатором "@android:id/list" (или список, если он находится в коде)

Поскольку вы не опубликовали файл макета для фрагмента, я не уверен, что здесь пошло не так. Следующий код показывает, как это должно быть, когда вы используете представление списка ListFragment по умолчанию. Если вы используете ListFragment, вы должны использовать дополнительные доступные методы, такие как setListAdapter и onListItemClick. Вы также можете сделать то же самое без использования ListFragment (используя только фрагмент).

Код фрагмента (изменен ваш фрагмент кода)

public class BasicFragment extends ListFragment {

    MyCustomAdapter adapter;

    @Override
    public void onCreate(Bundle si) {
        super.onCreate(si);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // not sure what you are doing here but data fetch should be asynchronous if it interacts with DB or makes network call
        FetchedData DT = FetchedData.StaticDataTransfer();
        RecepiesProperties[] AryObjaz = DT.getData();
        getdata(AryObjaz);
        adapter = new MyCustomAdapter(getActivity(), R.layout.listview_layout, Dataset);
        setListAdapter(adapter);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Toast t = Toast.makeText(getActivity(), "Message",
        Toast.LENGTH_SHORT);
        t.show();

    }
}

Кроме того, я изменил код вашего адаптера, чтобы облегчить повторное использование представлений, ваш текущий код не использовал повторное использование представлений и всегда увеличивал представления.

Код адаптера:

public class MyCustomAdapter extends ArrayAdapter<Recipes> {

    Context context;
    int layoutResourceId;
    Recipes data[] = null;
    Typeface typeface;
    public ImageLoader imageLoader;
    private LayoutInflater inflater;

    public MyCustomAdapter(Context context, int textViewResourceId, Recipes[] dataset) {
        super(context, textViewResourceId, dataset);
        this.layoutResourceId = textViewResourceId;
        this.context = context;
        this.data = dataset;
        imageLoader = new ImageLoader(context.getApplicationContext());
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        RecipesHolder holder = null;
        //recycling views
        if(null == row){
            row = inflater.inflate(layoutResourceId, parent, false);
            holder = new RecipesHolder();
            holder.imgIcon = (ImageView) row.findViewById(R.id.imageView1);
            holder.txtTitle = (TextView) row.findViewById(R.id.title);
            holder.category = (TextView) row.findViewById(R.id.category);
            holder.source = (TextView) row.findViewById(R.id.source);
            holder.country = (TextView) row.findViewById(R.id.country);
            holder.readytime = (TextView) row.findViewById(R.id.readytime);
            holder.tips = (Button) row.findViewById(R.id.tips);
            holder.fav = (Button) row.findViewById(R.id.fav);
            row.setTag(holder);
        }else{
            holder = (RecipesHolder)row.getTag();
        }
        Recipes ap = data[position];

        imageLoader.DisplayImage(ap.getIMAGENAME240(), holder.imgIcon);
        holder.txtTitle.setText(ap.getNAME());
        holder.category.setText(ap.getCATEGORY());
        holder.source.setText(ap.getSOURCE());
        holder.country.setText(ap.getCOUNTRY());
        holder.readytime.setText(ap.getREADYTIME());

        return row;
    }

    static class RecipesHolder {
        ImageView imgIcon;
        TextView txtTitle;
        TextView category;
        TextView source;
        TextView country;
        TextView readytime;
        Button tips;
        Button fav;
    }
}
person Abhishek Nandi    schedule 05.03.2013

Когда вы раздуваете свои представления, кажется, что в вашем представлении есть 2 кнопки:

это row.findViewById(R.id.tips);

и это row.findViewById(R.id.fav);

Вы должны либо удалить эти кнопки (замените их текстовыми представлениями, если вы не хотите, чтобы они нажимались)

Или, если вам нужны щелчки этих кнопок, вы можете использовать OnClickListener для каждой кнопки и другой OnClickListener для всего представления.


ПРИМЕР

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;

    //we only inflate if the row is null!!
    if(row == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);
        RecipesHolder holder = new RecipesHolder();
        holder.imgIcon = (ImageView) row.findViewById(R.id.imageView1);
        holder.txtTitle = (TextView) row.findViewById(R.id.title);
        holder.category = (TextView) row.findViewById(R.id.category);
        holder.source = (TextView) row.findViewById(R.id.source);
        holder.country = (TextView) row.findViewById(R.id.country);
        holder.readytime = (TextView) row.findViewById(R.id.readytime);
        holder.tips = (Button) row.findViewById(R.id.tips);
        holder.fav = (Button) row.findViewById(R.id.fav);
        //we set the tag of the view to this holder so we can get it everytime
        row.setTag(holder);
    }
    //change this to final so that you can use it inside your click listeners
    final Recipes ap = data[position];

    //here we get the holder of the view from its tag
    RecipesHolder holder = (RecipesHolder) row.getTag();

    //no changes to ur setup
    imageLoader.DisplayImage(ap.getIMAGENAME240(), holder.imgIcon);
    holder.txtTitle.setText(ap.getNAME());
    holder.category.setText(ap.getCATEGORY());
    holder.source.setText(ap.getSOURCE());
    holder.country.setText(ap.getCOUNTRY());
    holder.readytime.setText(ap.getREADYTIME());

    //now the click listeners

    //tips button
    holder.tips.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            //tips has been clicked
            //do whatever you want with `ap`
        }
    });
    //fav button
    holder.fav.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            //fav has been clicked
            //do whatever you want with `ap`
        }
    });
    //whole item click
    row.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            //the row has been clicked
            //do whatever you want with `ap`
        }
    });
    return row;
}
person Sherif elKhatib    schedule 04.03.2013
comment
@jeevamuthu, где кнопки с android:id="@+id/fav" и android:id="@+id/tips" - person Sherif elKhatib; 04.03.2013
comment
теперь см. listview_layout.xml. мне тоже нужны нажатия кнопок в списке и в строке списка - person jeevamuthu; 04.03.2013
comment
@jeevamuthu Я отредактировал ответ и исправил вашу функцию getView. Комментарии должны помочь вам лучше понять Холдера и, конечно же, прослушивателей кликов. - person Sherif elKhatib; 04.03.2013
comment
спасибо за ответ, мне нужно показать другой фрагмент, щелкнув эту строку списка. что я могу сделать для этого? - person jeevamuthu; 04.03.2013
comment
давайте продолжим обсуждение в чате - person Sherif elKhatib; 04.03.2013

Поместите следующий код в метод onViewCreated():

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {

    ListView list = (ListView) view.findViewById(android.R.id.list);

    list.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
                      Toast t = Toast.makeText(getActivity(), "Message",
                             Toast.LENGTH_SHORT);
                      t.show();
        }
    }); 

}

Проблема может заключаться в том, что представление еще не сконструировано в onViewCreate(), поэтому ставить слушатели туда нецелесообразно.

person Tool    schedule 27.02.2013
comment
Спасибо за ваш ответ. я реализовал этот метод, но не работает. пожалуйста, дайте любой образец. - person jeevamuthu; 27.02.2013
comment
Тост не появляется? - person Tool; 27.02.2013
comment
yes.toast не появляется. я использую CustomAdapter для просмотра списка. - person jeevamuthu; 27.02.2013
comment
Покажите нам свой класс MyCustomAdapter. - person Tool; 27.02.2013
comment
См. класс MyCustomAdapter. - person jeevamuthu; 27.02.2013

 lv.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
                //your code
        }
   });

я думаю это должно сработать

person Bigflow    schedule 27.02.2013

В адаптере есть метод areAllItemsEnabled(), он может быть полезен.

public abstract boolean areAllItemsEnabled()

Указывает, включены ли все элементы в этом адаптере. Если значение, возвращаемое этим методом, со временем изменится, нет гарантии, что оно вступит в силу. Если это правда, это означает, что все элементы доступны для выбора и нажатия (разделителя нет).

person Rodion Altshuler    schedule 10.03.2013

Просто поместите android:focusable="false" android:clickable="false" в макет. Для всех текстовых представлений, кнопок и т. д. Проблема решена.

person Ashwin S Ashok    schedule 09.12.2013

У меня была похожая проблема, я долго не мог понять в чем дело. Ранее мой фрагмент onListItemClick() открывал новую активность, но после возврата к фрагменту прослушиватель onListItemClick() больше не работал.

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    // additional code (e.g. open new activity)
}

Эта проблема была решена путем создания прослушивателя внутри моего пользовательского ArrayAdapter. Я поместил этот код внутри getView():

    rowView.setOnClickListener(new View.OnClickListener() {
        final int p = position;
        @Override
        public void onClick(View v) {
            Log.d("FeedListAdapter", "onClick()");
            openPost(p);    // for example
        }
    });

Я не спал всю ночь, исправляя это (сейчас 8 утра), я подумал, что должен опубликовать свое решение для всех, кто находится в похожем месте :)

person user2254319    schedule 27.03.2017