RecyclerView 23.2.x height=0dp causes onBind called for all items and scrollToPosition not working

痞子三分冷 提交于 2019-12-10 15:32:22

问题


UPDATE I just updated the support library to 23.3.0 and this problem does not seem to happen any more. I suppose this was a bug in the 23.2.X version. Well, this is not the first time that I have spent hours on a weird problem, and then later found that it was a bug of the Android SDK. END UPDATE

In the following code, I set layout_height="0dp" and layout_weight="1" to the recycler view to make it fill the remaining space of a linear layout. It looks to me that layout_height would not be needed because layout_weight is set, but omitting that attribute is considered an error, and examples I found in other questions on Stack Overflow suggest using "0dp".

The strange thing is that if I set layout_height="0dp", onBindViewHolder() is called for all items at once. That is, the debug output is like

onBindViewHolder(0)
...
onBindViewHolder(99)

If I set layout_height="1dp", onBindViewHolder() is called for only the first several items until scrolled. That is, the debug output is like

onBindViewHolder(0)
...
onBindViewHolder(8)

This does not happen with RecyclerView version 23.1.1, but happens with version 23.2.0 and 23.2.1 (e.g., com.android.support:recyclerview-v7:23.2.1), and it also makes the programatic scrolling not working. Why is it so? Am I supposed to use "1dp" in this case?

The following are the entire source codes.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>

<FrameLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:background="@android:color/holo_green_dark"
    />

<View
    android:layout_width="1dp"
    android:layout_height="match_parent"
    android:background="#ff111111"/>

<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="3"
    android:orientation="vertical">

    <FrameLayout
        android:background="@android:color/holo_orange_light"
        android:layout_width="match_parent"
        android:layout_height="50dp">

    </FrameLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/mylist"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_weight="1"
        >

    </android.support.v7.widget.RecyclerView>

    <FrameLayout
        android:background="@android:color/holo_blue_bright"
        android:layout_width="match_parent"
        android:layout_height="50dp">
    </FrameLayout>
</LinearLayout>

my_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:orientation="horizontal"
          android:layout_width="match_parent"
          android:clickable="true"
          android:focusable="true"
          android:id="@+id/itemRect"
          android:background="?android:attr/selectableItemBackground"
          android:layout_height="wrap_content">

<ImageView
    android:src="@android:drawable/ic_menu_camera"
    android:layout_width="48sp"
    android:layout_height="48sp"/>
<TextView
    tools:text="Hello world"
    android:id="@+id/name"
    android:gravity="center_vertical"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:layout_height="48sp"/>

MainActivity.java

public class MainActivity extends AppCompatActivity
{
String TAG = this.getClass().getName();
RecyclerView mylist;
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mylist = (RecyclerView)findViewById(R.id.mylist);

    ArrayList<String> source = new ArrayList<>();
    for(int i =0; i< 100; i++)
    {
        source.add("List item " + i);
    }

    LinearLayoutManager lay = new LinearLayoutManager(mylist.getContext());
    mylist.setLayoutManager(lay);
    MyAdapter adap = new MyAdapter(source);
    mylist.setAdapter(adap);
}


class MyViewHolder extends RecyclerView.ViewHolder
{
    TextView name;
    public MyViewHolder(View itemView)
    {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.name);
    }

    public void bind(String item)
    {
        name.setText(item);
    }
}
class MyAdapter extends RecyclerView.Adapter<MyViewHolder>
{
    List<String> items;
    public MyAdapter(List<String> items)
    {
        this.items = items;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_item, null);
        MyViewHolder vh = new MyViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position)
    {
        Log.d(TAG, "onBindViewHolder(" + position + ")");
        holder.bind(items.get(position));
    }

    @Override
    public int getItemCount()
    {
        return items.size();
    }
}

来源:https://stackoverflow.com/questions/36065736/recyclerview-23-2-x-height-0dp-causes-onbind-called-for-all-items-and-scrolltopo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!