如何动态更改适配器布局?

3
我有一个自定义的适配器,我希望根据方向改变行布局。我有一个名为`setOrientation`的函数,在其中修改布局并调用`notifyDataSetChanged()`,希望一切都会被重置。不幸的是,似乎并不是这样,即使在调用`getView()`的第一次中,`notifyDataSetChanged()`之后,`convertView`仍然不为空,所以布局没有改变。有没有办法重置这个`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;
    }
}

或许在 ListView 上调用 removeAllViews() 方法? - Mike M.
@MikeM,很遗憾它不起作用 :( - jul
我已经添加了解释和示例代码。 - tom91136
3个回答

4

最快的方法: 创建一个新的TableRowsAdapter实例并再次设置它(将方向作为构造函数参数)。 例如:

 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;
    }

}

正确的方法:

当你使用setOrientation时,应该先填充新布局并将convertView替换为它。

原因: notifyDatasetChanged()不知道你将要替换布局,所以它只是重复利用了视图,导致convertView不为空。

在布局R.layout.table_row_landR.layout.table_row中为根视图添加一个唯一的id,

例如:

R.layout.table_row_land的id为R.id.row_landR.layout.table_row的id为R.id.row_normal

根视图会变成这样:

<?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>

下面是一个简单的伪代码实现:

@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;
}

v.getId() дёҚдјҡиҝ”еӣһеёғеұҖзҡ„ IDпјҢеӣ жӯӨ v.getId() != layout жҖ»жҳҜдёәзңҹпјҢеҜјиҮҙж— жі•еӣһ收еҲ©з”ЁгҖӮ - jul
我做了类似的事情,但是使用了自定义标签对象:class CustomTagObject { public CustomTagObject(ViewHolder viewHolder, int layout){ this.viewHolder = viewHolder; this.layout = layout; } public ViewHolder viewHolder; public int layout; } - jul

1
创建一个名为table_row.xml的文件并将其放置在res/layout文件夹中,再创建另一个同名文件table_row.xml并将其与table_row_land.xml相同,将其放置在res/layout-land文件夹中。

在适配器中设置table_row.xml

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

        ViewHolder holder;
        View v = convertView;

        if (v == null) {

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

     }

0

在您的布局中创建两个视图(在同一个XML文件中),并将第二个布局的可见性设置为gone。像您已经做过的那样进行充气,并在getView方法中根据方向设置视图的可见性。

@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 */

      if(portrait) {
      // then visiblity of first View or View Group set Visible and
      // visiblity of second View or View Group set Gone
   } else {
   // then visiblity of first View or View Group set GONE and
      // visiblity of second View or View Group set Visible. 
    }

    return v;
}

这将需要在ViewHolder中重复字段,并且视图计数会增加一倍。 - tom91136

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接