Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change adapter layout dynamically?

I have a custom Adapter in which I'd like the row layout to change according to the orientation.

I have a function setOrientation in which I modify the layout and call notifyDataSetChanged(), hoping that everything would be reset.

Unfortunately, it seems that it is not because even after notifyDataSetChanged(), the convertView in the first call of getView() is not null, so the layout is not changed.

Is there any way to reset this convertView?

public class TableRowsAdapter extends BaseAdapter {

    private LayoutInflater layoutInflater;

    private int layout;

    private TableRow[] items;

    private class ViewHolder {
        /* some stuff */
    }

    public TableRowsAdapter(Context context, TableRow[] tableRowList)
    {
        super();
        this.items = tableRowList;
        this.layoutInflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );

        /* Set default layout to portrait */
        layout = R.layout.table_row;
    }

    public void setOrientation(int orientation){

        if(orientation== Configuration.ORIENTATION_LANDSCAPE){
            layout = R.layout.table_row_land;
        }
        else{
            layout = R.layout.table_row;
        }

        notifyDataSetChanged();
    }

    public int getCount()
    {
        return items.length;
    }

    public TableRow getItem(int position)
    {
        return items[position];
    }

    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        View v = convertView;

        if (v == null) {

            v = layoutInflater.inflate(layout, parent, false);

            holder = new ViewHolder();

            /* some stuff */

            v.setTag(holder);
        } else {
            holder = (ViewHolder) v.getTag();
        }

        TableRow item = getItem(position);

        /* some stuff */

        return v;
    }
}
like image 471
jul Avatar asked Mar 11 '26 10:03

jul


1 Answers

Fastest way: create a new instance of TableRowsAdapter and set it again(make the orientation a constructor parameter). Example:

 public TableRowsAdapter(Context context, TableRow[] tableRowList, int orientation)
  {
    super();
    this.items = tableRowList;
    this.layoutInflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );


    if(orientation== Configuration.ORIENTATION_LANDSCAPE){
        layout = R.layout.table_row_land;
    }
    else{
        layout = R.layout.table_row;
    }

}

The proper way:

when you setOrientation, inflate the new layout and replace convertView with that

Reason: notifyDatasetChanged() does not know that you'll replace the layout, so it simply recycles the view thus making convertView not null.

In layout R.layout.table_row_land and R.layout.table_row, add an unique id for the root view,

Example:

id for R.layout.table_row_land is R.id.row_land and R.layout.table_row is R.id.row_normal

The root view would become something like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/row_normal"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical" >
<!-- the rest of the layout  -->

</LinearLayout>

And here's a simple pseudo implementation:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    ViewHolder holder;
    View v = convertView;

    // check if convertView needs a new layout here
    if (v == null || (v.getId() == R.id.row_normal && layout == R.layout.table_row_land)) {

        v = layoutInflater.inflate(layout, parent, false);

        holder = new ViewHolder();

        /* some stuff */

        v.setTag(holder);
    } else {
        holder = (ViewHolder) v.getTag();
    }

    TableRow item = getItem(position);

    /* some stuff */

    return v;
}
like image 101
tom91136 Avatar answered Mar 13 '26 01:03

tom91136



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!