A custom ListView with a custom adapter in Android Studio

dragon3002 picture dragon3002 · Feb 9, 2015 · Viewed 22k times · Source

Will I don't what is the problem. There are no errors nothing, and the program working perfectly. However, when I click on an item on list View it does not do anything. In other word the "Toast" won't pass

This My main class:

public class ViewListAct extends ActionBarActivity {


private ListView list;
private final String[] names_1 = {"McDonald's", "Subway", "Pizza Hut", "Burger King"};
private final String[] img_1   = {"mcd", "mcd", "mcd", "mcd"};
private Activity context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.view_list);
    list = (ListView) findViewById(R.id.listview);

    AdapterView adapter = new AdapterView(this, img_1, names_1);
    list.setAdapter(adapter);


      list.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(android.widget.AdapterView<?> parent, View view, int position, long id) {
           Toast.makeText(getApplicationContext(), names_1[position], Toast.LENGTH_LONG).show();


        }
    });

}

This my Custom Adapter Class:

public class AdapterView extends ArrayAdapter<String> {

    private Activity context_1;
    private String[] names_1;
    private String[] img_1;

public AdapterView(Activity context, String[] img, String[] names) {
    super(context, R.layout.pic_letf_tv_right, names);

    context_1 = context;
    this.names_1 = names;
    this.img_1 = img;
}

public View getView(int position, View view, ViewGroup parent){
    LayoutInflater l_i_f = context_1.getLayoutInflater();
    View rv = l_i_f.inflate(R.layout.pic_letf_tv_right, null); 

    TextView tv_l = (TextView) rv.findViewById(R.id.tv_view);
    tv_l.setText(names_1[position]);

    ImageView imageView = (ImageView) rv.findViewById(R.id.log_img);
    int id = context_1.getResources().getIdentifier(img_1[position], "drawable", context_1.getPackageName());
    imageView.setImageResource(id);

    return rv;
}

}

This my Custom Row xml file:

<?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent" android:layout_height="match_parent"
   android:clickable="true"
   android:orientation="horizontal"
    >

    <ImageView
    android:layout_width="500px"
    android:layout_height="500px"
    android:id="@+id/log_img"
    />

    <TextView
    android:id="@+id/tv_view"
    android:layout_gravity="center"
    android:gravity="center"
    android:layout_width="match_parent"
    android:layout_height="500px"
    android:textColor="#FFFFFF"
    android:textSize="18dp"/>
    </LinearLayout>

This my ListView xml file:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="always"
tools:context=".ViewList">



<ListView
    android:id="@+id/listview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scrollingCache="false"
    android:smoothScrollbar="true"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:background="#000000" />

Could anyone tell me what am I doing wrong.

Answer

GIGAMOLE picture GIGAMOLE · Feb 9, 2015

At first use ViewHolder pattern. At second extend BaseAdapter not AdapterView. At third delete android:clickable="true" from row.xml. Clickable state must have ListView in method onItemClickListener, not own row.

Updated

For the Customized listview you can use BaseAdapter.

And With Adapter Class you it have some tips to make it smooth , for that you can refer this

Its also about resusability already created row's control instances.For that ViewHolder pattern i prefer to use to hold the objects. Please check this for more detail

Which is missing in your code of the adapter's getView Method.

For more explanation i leave comment in Adapter's getView Method.

Class to hold the details if you are gng to use thn naming convention should be proper here first the name is "Object" which is wrong.

Activity

private ListView list;
    private final ArrayList<RestaurantsDetails> pairs = new ArrayList<RestaurantsDetails>();
    private Activity context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        pairs.add(new RestaurantsDetails("McDonald's", "mcd"));
        pairs.add(new RestaurantsDetails("Subway", "mcd"));
        pairs.add(new RestaurantsDetails("Pizza Hut", "mcd"));
        pairs.add(new RestaurantsDetails("Burger King", "mcd"));

        list = (ListView) findViewById(R.id.listview);

        AdapterViewCustom adapter = new AdapterViewCustom(this, pairs);
        list.setAdapter(adapter);

        list.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(android.widget.AdapterView<?> parent,
                    View view, int position, long id) {
                Toast.makeText(getApplicationContext(),
                        pairs.get(position).name, Toast.LENGTH_LONG).show();
            }
        });

    }

DataLayer Class

/**
     * Use proper name For the class. Should not use the name like "Object" or
     * the class which is already used by framework
     * 
     */
    public class RestaurantsDetails {

        public String name;
        public String img;

        public RestaurantsDetails(String name, String img) {
            this.name = name;
            this.img = img;
        }

    }

Adapter

public class AdapterViewCustom extends BaseAdapter {

        private Activity context_1;

        private ArrayList<RestaurantsDetails> pairs;

        public AdapterViewCustom(Activity context,
                ArrayList<RestaurantsDetails> pairs) {
            context_1 = context;
            this.pairs = pairs;
        }

        @Override
        public int getCount() {
            return pairs.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

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

            if (convertView == null) {
                convertView = LayoutInflater.from(context_1).inflate(
                        R.layout.custom_row, null);
                viewHolder = new ViewHolder();
                viewHolder.img = (ImageView) convertView
                        .findViewById(R.id.log_img);
                viewHolder.txt = (TextView) convertView
                        .findViewById(R.id.tv_view);
                /**
                 * At very first time when the List View row Item control's
                 * instance is created it will be store in the convertView as a
                 * ViewHolder Class object for the reusability purpose
                 **/
                convertView.setTag(viewHolder);
            } else {
                /**
                 * Once the instance of the row item's control it will use from
                 * already created controls which are stored in convertView as a
                 * ViewHolder Instance
                 * */
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.txt.setText(pairs.get(position).name);
            int id = context_1.getResources().getIdentifier(
                    pairs.get(position).img, "drawable",
                    context_1.getPackageName());
            viewHolder.img.setImageResource(id);

            return convertView;
        }

        public class ViewHolder {
            public final ImageView img;
            public final TextView txt;

        }
    }