Archive for March, 2013

Guide: Android – MultiClickable ListView:

Well today I want to talk about implementation of a multiclickable list.
And what do I mean by that? Well what I mean is that every list item has
more then one location where you can press it following by different operation.

So lets for example take a row where you want to place a CheckBox, ImageView
and a TextView while all of them are clickable. Meaning that you can click the
row it self for going to another Actvity for more details on the row, check its
CheckBox or press the ImageView to perform another operation.

So what you should do is:

1. First create an XML layout file for your ListView row:

<LinearLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <CheckBox 
        android:id="@+id/cbCheckListItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_marginLeft="10dp" />
    <TextView
        android:id="@+id/tvItemTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="item string" />
    <ImageView
        android:id="@+id/iStatus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:contentDescription="@drawable/ic_launcher"
        android:src="@drawable/ic_launcher" /> 
</LinearLayout>

2. Second in your java code define a ViewHolder, a ViewHolder
is designed to hold the row views and that way operating more quickly.

static class ViewHolder 
{
    TextView title;
    CheckBox checked;
    ImageView changeRowStatus;
}

3. Now we have to define CustomArrayAdapter, using the array adapter
we can define precisely what is the desired output for each row based on the content of this
row or it’s position. We can do so by overriding the getView method:

private class CustomArrayAdapter extends ArrayAdapter<RowData>
{	
    private ArrayList<RowData> list;
    
    //this custom adapter receives an ArrayList of RowData objects.
    //RowData is my class that represents the data for a single row and could be anything.
    public CustomArrayAdapter(Context context, int textViewResourceId, ArrayList<RowData> rowDataList) 
    {
        //populate the local list with data.
        super(context, textViewResourceId, rowDataList);
        this.list = new ArrayList<RowData>();
        this.list.addAll(rowDataList);
    }
		
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        //creating the ViewHolder we defined earlier.
        ViewHolder holder = new ViewHolder();) 
        
        //creating LayoutInflator for inflating the row layout.
        LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //inflating the row layout we defined earlier.
        convertView = inflator.inflate(R.layout.row_item_layout, null);
        
        //setting the views into the ViewHolder.
        holder.title = (TextView) convertView.findViewById(R.id.tvItemTitle);
        holder.changeRowStatus = (ImageView) convertView.findViewById(R.id.iStatus);
        holder.changeRowStatus.setTag(position);
 
        //define an onClickListener for the ImageView.
        holder.changeRowStatus.setOnClickListener(new OnClickListener() 
        {			
            @Override
            public void onClick(View v) 
            {
                Toast.makeText(activity, "Image from row " + position + " was pressed", Toast.LENGTH_LONG).show();
            }
        });
        holder.checked = (CheckBox) convertView.findViewById(R.id.cbCheckListItem);
        holder.checked.setTag(position);

        //define an onClickListener for the CheckBox.
        holder.checked.setOnClickListener(new OnClickListener() 
        {		
            @Override
            public void onClick(View v)
            {
                //assign check-box state to the corresponding object in list.    
                CheckBox checkbox = (CheckBox) v;
                rowDataList.get(position).setChecked(checkbox.isChecked());
                Toast.makeText(activity, "CheckBox from row " + position + " was checked", Toast.LENGTH_LONG).show();	 
            }
        });

        //setting data into the the ViewHolder.
        holder.title.setText(rowDataList.get(position).getName());
        holder.checked.setChecked(rowDataList.get(position).isChecked());

        //return the row view.
        return convertView;
    }
}

4. Now you need to set this adapter, as the adapter of your ListView.
this ListView can be created in java or using an XML file, in this case I’m using a list that was
defined in the XML file using the “list” id:

public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_layout); 
    ListView list = (ListView)findViewById(R.id.list);
    CustomArrayAdapter dataAdapter = new CustomArrayAdapter(this, R.id.tvItemTitle, rowDataList);
    list.setAdapter(dataAdapter);
}

5. Finally if we want to be able to press the row it self and not only a certain view in it
we should assign an onItemClickListener to the ListView:

list.setOnItemClickListener(new OnItemClickListener() 
{
    public void onItemClick(AdapterView<?> parent, View view,int position, long id) 
    {
        Toast.makeText(activity, "row " + position + " was pressed", Toast.LENGTH_LONG).show();
    }
});
March 31, 2013Emil Adjiev 8 Comments »
FILED UNDER :Guide , Guide - Android Development