Question

My final outcome is a simple Chat bubble style ListView.

  1. I have two layout files for left and right bubbles
  2. In my Adapter's getView, I would check a flag and inflate the required layout
  3. I am also using the holder concept.

    public class Holder {
        TextView userName;
        TextView message;
        CheckBox box;
    }    
    
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        Holder holder;
        OneComment coment = getItem(position);
    
        if (row == null) {
            holder = new Holder();
            if (coment.left) {
                row = inflater.inflate(R.layout.listitem_left_chat, null, false);
                holder.message = (TextView) row.findViewById(R.id.comment);
                holder.box = (CheckBox) row.findViewById(R.id.checkBox1);
            } else {
                row = inflater.inflate(R.layout.listitem_right_chat, null, false);
                holder.message = (TextView) row.findViewById(R.id.comment2);
                holder.box = (CheckBox) row.findViewById(R.id.checkBox2);
            }
        holder.message.setText(coment.comment);
        holder.box.setChecked(coment.left);
        }
        return row;
    }
    

I'm getting the desired outcome. I still want to know if the approach is correct. If not, which is the best approach?

Was it helpful?

Solution

Adapter can work with different views. You should override two methods: getViewTypeCount() and getItemViewType(int position). In your case:

private static final int TYPES_COUNT = 2;
private static final int TYPE_LEFT = 0;
private static final int TYPE_RIGHT = 1;

@Override
public int getViewTypeCount() {
    return TYPES_COUNT;
}

@Override
public int getItemViewType (int position) {
    if (getItem(position).left) {
        return TYPE_LEFT;
    }
    return TYPE_RIGHT;
}

public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    Holder holder;
    OneComment coment = getItem(position);

    if (row == null) {
        holder = new Holder();
        if (getItemViewType (position) == TYPE_LEFT) {
            row = inflater.inflate(R.layout.listitem_left_chat, null, false);
            holder.message = (TextView) row.findViewById(R.id.comment);
            holder.box = (CheckBox) row.findViewById(R.id.checkBox1);
        } else {
            row = inflater.inflate(R.layout.listitem_right_chat, null, false);
            holder.message = (TextView) row.findViewById(R.id.comment2);
            holder.box = (CheckBox) row.findViewById(R.id.checkBox2);
        }

        row.setTag(holder);
    } else {
        holder = (Holder)row.getTag();
    }

    holder.message.setText(coment.comment);
    holder.box.setChecked(coment.left);

    return row;
}

public class Holder {
    TextView userName;
    TextView message;
    CheckBox box;
}

UPD:

Explanation:

getItemViewType should return an integer that identifies what type of View that will be created by getView(int, View, ViewGroup) for the specified item. Two views should return the same result if one can be converted to the other in getView.

getViewTypeCount should return an integer with the number of types of Views that the Adapter will handle.

Behind the scenes Android uses the View type to determine what type of View should be passed in to the getView method. You can think of it as creating multiple buckets of Views that can be reused and thus avoid the penalty of inflating a new view each time a new list item becomes visible.

As the user scrolls down the ListView the framework will recycle rows that are no longer visible and add them to the appropriate bucket for reuse. When a new Header or Event item comes into view the framework will check to see if one of those views already exists in the bucket of recycled views, if so it will be passed in as the convertView to getView method.

OTHER TIPS

// try this way,hope this will help you...

See below how to use single layout instead of two separate layout.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/lnrRightChat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:padding="5dp"
        android:layout_marginRight="20dp">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">
            <TextView
                android:id="@+id/txtRightMessage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Right Side Chat Message "/>
        </LinearLayout>
        <CheckBox
            android:id="@+id/chkRight"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/lnrLeftChat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:gravity="center_vertical"
        android:padding="5dp"
        android:layout_marginLeft="20dp">
        <CheckBox
            android:id="@+id/chkLeft"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">
            <TextView
                android:id="@+id/txtLeftMessage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Left Side Chat Message"/>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

See below how to use above layout in adapter.

public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if(convertView==null){
                convertView = LayoutInflater.from(context).inflate(R.layout.activity_main,null,false);
                holder = new ViewHolder();
                holder.lnrLeftChat = (LinearLayout) convertView.findViewById(R.id.lnrLeftChat);
                holder.lnrRightChat = (LinearLayout) convertView.findViewById(R.id.lnrRightChat);
                holder.txtRightMessage = (TextView) convertView.findViewById(R.id.txtRightMessage);
                holder.txtLeftMessage = (TextView) convertView.findViewById(R.id.txtLeftMessage);
                holder.chkRight = (CheckBox) convertView.findViewById(R.id.chkRight);
                holder.chkLeft = (CheckBox) convertView.findViewById(R.id.chkLeft);
                convertView.setTag(holder);
            }else{
                holder = (ViewHolder) convertView.getTag();
            }
            OneComment coment = getItem(position);
            if(coment.left){
                holder.lnrLeftChat.setVisibility(View.VISIBLE);
                holder.lnrRightChat.setVisibility(View.VISIBLE);
                holder.txtLeftMessage.setText(coment.comment);
                holder.chkLeft.setText(coment.left);
            }else{
                holder.lnrRightChat.setVisibility(View.VISIBLE);
                holder.lnrRightChat.setVisibility(View.VISIBLE);
                holder.txtRightMessage.setText("");
            }
            return convertView;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top