Home » Android » android – Dynamically change the row layout of a ListView

android – Dynamically change the row layout of a ListView

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’m working on a chat module in an app, where I want the messages from two participants on opposing alignment (other user left-aligned and my own msg right-aligned). Right now, my row layout is passed in through a static layout xml (with msg and avatar left-aligned). Is there a way to modify the view dynamically, or is there a way to pass an alternative row layout for the UI system to pick at runtime?

How to&Answers:

You can do that inside the getView() method of your ArrayAdapter class (assuming you are defining your own ArrayAdapter).

You could have something like this:

private class YourAdapter extends ArrayAdapter<Message> {
        private final LayoutInflater mLayoutInflater;

    YourAdapter(YourListActivity activity) {
        super(mContext, 0);
        mLayoutInflater = LayoutInflater.from(activity);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            // Inflate your view
            convertView = mLayoutInflater.inflate(R.layout.list_view_item, parent, false);
            mViewHolder = new ViewHolder();
            mViewHolder.avatar = (ImageView) convertView.findViewById(R.id.placeholder);
            mViewHolder.message = (TextView) convertView.findViewById(R.id.message);

            convertView.setTag(mViewHolder);
        } else {
            mViewHolder = (ViewHolder) convertView.getTag();
        }

        final Message message = getItem(position);

        mViewHolder.message.setText(message.getMessage());
        // etc. Manipulate your views as you wish


        return convertView;
    }
}


   private static class ViewHolder {
        TextView message;
        ImageView avatar;
   }

getView will get called each time you the ListView is modified (like when you scroll or when new elements are added to it), so you can manipulate each row
as you want there.
Don’t forget to set the array adapter of the ListView to an instance of this class.

listView.setListAdapter(new mYourAdapter);  

Answer:

private LayoutInflater mInflater;
private static final int TYPE_ITEM1 = 0;
private static final int TYPE_ITEM2 = 1;
ArrayList<String> s= new ArrayList<String>();
int time;
String names[]={"raghu","pavan","rakesh","raghu","pavan"};
Context c;

@Override
public int getItemViewType(int position) {
    if((position%2)==0)
    {
        return 0;
    }
    return 1;       
}

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

public Customlistadapter(CustomListView customListView, int time) {
    // TODO Auto-generated constructor stub
    for(int i=0;i<=10;i++)
    {
        s.add("Raghu");
    }
    this.mInflater = LayoutInflater.from(customListView);  
    c=customListView;
    this.time=time;
}
public int getCount() {
    return s.size();
}

public Object getItem(int arg0) {
    return s.get(arg0);
}

public long getItemId(int arg0) {
return 0;
}

@Override
public void notifyDataSetChanged() {
    super.notifyDataSetChanged();
    if(CustomListView.chk==true)
    {
    s.add("Raghu"); 
    }
    else if(CustomListView.chk==false)
    {
    s.remove(s.size()-1);
    }       
}
@Override
public void notifyDataSetInvalidated() {
    super.notifyDataSetInvalidated();
}
public View getView(final int arg0, View arg1, ViewGroup arg2) {
    ViewHolder vh;
    vh= new ViewHolder();
    int type = getItemViewType(arg0);
    System.out.println("getView " + arg0  + " type = "+type);
    if(arg1==null )
    {
         switch (type) {
         case TYPE_ITEM1:
             arg1=mInflater.inflate(R.layout.listview, arg2,false);             
            vh.tv= (TextView)arg1.findViewById(R.id.textView1);
            vh.tv1= (TextView)arg1.findViewById(R.id.textView2);
            vh.tv2=(TextView)arg1.findViewById(R.id.textView3);
            vh.tv.setText(s.get(arg0));
            vh.tv1.setText(s.get(arg0));
            vh.tv2.setText(Integer.toString(time));
             break;
         case TYPE_ITEM2:
             arg1=mInflater.inflate(R.layout.listviewimg, arg2,false);
            vh= new ViewHolder();
            vh.iv1= (ImageView)arg1.findViewById(R.id.iv1);
            vh.iv2= (ImageView)arg1.findViewById(R.id.iv2);
            vh.iv1.setBackgroundResource(R.drawable.ic_launcher);
            vh.iv2.setBackgroundResource(R.drawable.ic_launcher);
             break;
     }
        arg1.setTag(vh);
    }
    else
    {
        vh= (ViewHolder) arg1.getTag();
    }
    return arg1;
}

1.Your Cusom Adapter class extends base Adapter.
2. Override getItemViewType() and getViewTypeCount()
3. Inflate a view depending on the type in getView()

Answer:

A way I have been shown to do it (im not sure if its best practice or not!) is to have both views in one XML file. At run time you can get a reference to each view (using findViewById) and set the visible property to gone of the one you dont want.

Ill try and find some sample code if thats not clear?

Answer:

My code:

private void setAlignment(ViewHolder holder, boolean isOutgoing, QBChatMessage chatMessage) {

    if (!isOutgoing) {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.contentWithBG.getLayoutParams();
        layoutParams.gravity = Gravity.LEFT;
        holder.contentWithBG.setLayoutParams(layoutParams);

        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) holder.content.getLayoutParams();
        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
        lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        holder.content.setLayoutParams(lp);

        layoutParams = (LinearLayout.LayoutParams) holder.txtInfo.getLayoutParams();
        layoutParams.gravity = Gravity.RIGHT;
        holder.txtInfo.setLayoutParams(layoutParams);

        if (holder.txtMessage != null) {
            holder.contentWithBG.setBackgroundResource(R.drawable.bubblevioletcopy);
            layoutParams = (LinearLayout.LayoutParams) holder.txtMessage.getLayoutParams();
            layoutParams.gravity = Gravity.RIGHT;
            holder.txtMessage.setLayoutParams(layoutParams);
            holder.lnr_image.setLayoutParams(layoutParams);
        } else {
            holder.contentWithBG.setBackgroundResource(android.R.color.transparent);
        }
    } else {
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.contentWithBG.getLayoutParams();
        layoutParams.gravity = Gravity.LEFT;
        holder.contentWithBG.setLayoutParams(layoutParams);

        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) holder.content.getLayoutParams();
        lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0);
        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        holder.content.setLayoutParams(lp);

        layoutParams = (LinearLayout.LayoutParams) holder.txtInfo.getLayoutParams();
        layoutParams.gravity = Gravity.RIGHT;
        holder.txtInfo.setLayoutParams(layoutParams);

        if (holder.txtMessage != null) {
            holder.contentWithBG.setBackgroundResource(R.drawable.bubblegraycopy);
            layoutParams = (LinearLayout.LayoutParams) holder.txtMessage.getLayoutParams();
            layoutParams.gravity = Gravity.RIGHT;
            holder.txtMessage.setLayoutParams(layoutParams);
        } else {
            holder.contentWithBG.setBackgroundResource(android.R.color.transparent);
        }
    }
}