Android notifyItemChanged()使RecyclerView滚动并跳到UP

Android notifyItemChanged()使RecyclerView滚动并跳到UP,android,android-recyclerview,Android,Android Recyclerview,我有一个带有适配器的RecycleView,它显示服务器列表 并且用户必须选择一台服务器 在onClick()方法中调用notifyItemChanged(previousPosition)时 要取消选择旧服务器并选择新服务器, 这使得ReCycliVIEW列表正好在列表中间跳起来。 当我点击RecycleView列表中最后2或3台服务器时,这个问题就发生了 以下是我的RecyclerView.Adapter的代码: public class ServerAdapter extends Recy

我有一个带有适配器的RecycleView,它显示服务器列表 并且用户必须选择一台服务器

在onClick()方法中调用notifyItemChanged(previousPosition)时 要取消选择旧服务器并选择新服务器, 这使得ReCycliVIEW列表正好在列表中间跳起来。

当我点击RecycleView列表中最后2或3台服务器时,这个问题就发生了

以下是我的RecyclerView.Adapter的代码:

public class ServerAdapter extends RecyclerView.Adapter<ServerAdapter.ServerViewHolder> {

    private List<Server> listServers = new ArrayList<>();
    private int[] icons = new int[]{R.drawable.server1,R.drawable.server2,R.drawable.server3,R.drawable.server4,R.drawable.server5,R.drawable.server6,R.drawable.offline};
    private int selected = 0;
    private int previousSelected = 0;

    public ServerAdapter(List<Server> listServers){
        this.listServers = listServers;
    }

    @Override
    public ServerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.server_relative_layout,parent,false);
        return new ServerViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ServerViewHolder holder, final int position) {
        if(position == selected){
            holder.getBackground().setSelected(true);
        }else{
            holder.getBackground().setSelected(false);
        }
        holder.getBackground().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(position != selected){
                    previousSelected = selected;
                    selected = position;
                    holder.getBackground().setSelected(true);
                    notifyItemChanged(previousSelected);
                }
            }
        });
        holder.getImageServer().setImageResource(icons[position%6]);
        holder.getTextNameServer().setText(listServers.get(position).getName());
        holder.getTextConnected().setText(listServers.get(position).getUrl());
    }

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

    public class ServerViewHolder extends RecyclerView.ViewHolder{
        private ImageView imageServer;
        private TextView textNameServer;
        private TextView textConnected;
        private View background;
        public ServerViewHolder(View itemView) {
            super(itemView);
            imageServer = (ImageView)itemView.findViewById(R.id.imageServer);
            textNameServer = (TextView)itemView.findViewById(R.id.textNameServer);
            textConnected = (TextView)itemView.findViewById(R.id.textConnected);
            background = itemView;
        }

        public ImageView getImageServer() {
            return imageServer;
        }

        public TextView getTextConnected() {
            return textConnected;
        }

        public TextView getTextNameServer() {
            return textNameServer;
        }

        public View getBackground() {
            return background;
        }
    }
}
公共类ServerAdapter扩展了RecyclerView.Adapter{ private List listServers=new ArrayList(); private int[]icons=new int[]{R.drawable.server1,R.drawable.server2,R.drawable.server3,R.drawable.server4,R.drawable.server5,R.drawable.server6,R.drawable.offline}; 选择的私有int=0; private int previousSelected=0; 公用服务器适配器(列表服务器){ this.listServers=listServers; } @凌驾 公共服务器ViewHolder onCreateViewHolder(视图组父级,int-viewType){ View=LayoutInflater.from(parent.getContext()).flate(R.layout.server\u relative\u layout,parent,false); 返回新的ServerViewHolder(视图); } @凌驾 BindViewHolder上的公共无效(最终服务器ViewHolder,最终int位置){ 如果(位置==选定){ holder.getBackground().setSelected(true); }否则{ holder.getBackground().setSelected(false); } holder.getBackground().setOnClickListener(新视图.OnClickListener()){ @凌驾 公共void onClick(视图v){ 如果(位置!=选定){ previousSelected=已选择; 选择=位置; holder.getBackground().setSelected(true); notifyItemChanged(先前选择); } } }); holder.getImageServer().setImageResource(图标[位置%6]); holder.getTextNameServer().setText(listServers.get(position.getName()); holder.gettexconnected().setText(listServers.get(position.getUrl()); } @凌驾 public int getItemCount(){ 返回listServers.size(); } 公共类ServerViewHolder扩展了RecyclerView.ViewHolder{ 私有ImageView图像服务器; 私有TextView textNameServer; 私有文本视图文本连接; 私视背景; 公共服务器视图持有者(视图项视图){ 超级(项目视图); imageServer=(ImageView)itemView.findViewById(R.id.imageServer); textNameServer=(TextView)itemView.findViewById(R.id.textNameServer); textConnected=(TextView)itemView.findViewById(R.id.textConnected); 背景=项目视图; } 公共ImageView getImageServer(){ 返回图像服务器; } 公共文本视图getTextConnected(){ 返回已连接的文本; } 公共文本视图getTextNameServer(){ 返回textNameServer; } 公共视图getBackground(){ 返回背景; } } } 有什么解决这个问题的办法吗?谢谢

当我指定布局高度并且不让它包装内容时,问题就发生了

<android.support.v7.widget.RecyclerView
    android:layout_width="wrap_content"
    android:layout_height="400dp"
    android:id="@+id/serverRecyclerView"
    android:layout_margin="10dp"
/>

或者当我把它放在下面,比如说:

<android.support.v7.widget.RecyclerView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/serverRecyclerView"
    android:layout_margin="10dp"
    android:layout_below="@+id/image"/>

我的代码就是:

<android.support.v7.widget.RecyclerView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/serverRecyclerView"
    android:layout_margin="10dp"
    android:layout_alignTop="@+id/imageBall"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_toRightOf="@+id/camera"
    android:layout_toEndOf="@+id/camera"/>

我不知道为什么,但我使用了:

RecyclerView.setHasFixedSize(true)

这对我有用。我希望它能有所帮助。

看起来这是一个bug:

最好的解决方法似乎是Bart将RecyclerView的LinearLayoutManager的AutoMeasure属性设置为false

将FixedSize设置为true解决方案有太多的副作用


setHasFixedSize(true)

我遇到了类似的问题,只需处理xml布局文件即可。
不要在RecyclerView或RecyclerView的父视图中使用下面的
layout\u、上面的
layout\u或其他类似属性。
您可以使用
LinearLayout weight
layout\u marginBottom
或其他方法来实现

layout\u下方
或其他。

如果有人无意中发现此问题,请尝试使用

RecyclerView.ItemAnimator animator = myRecyclerListView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
    ((SimpleItemAnimator)animator).setSupportsChangeAnimations(false);
}
yourRecyclerView.notifyItemChanged(int position, Object payload);
这一个帮了我的忙

使用

同样有效,但在一些边缘案例中,回收者的观点表现得很怪异。祝你好运


android:genderantfocusability=“blocksDescendants”
我的RecyclerView在ConstraintLayout中,我也遇到了这样的问题,调用RecyclerView的LayoutManager的
setAutoMeasureEnabled(false)
并没有为我解决这个问题,而且这个方法在28.0.0版本中被弃用。我所做的是,我用RelativeLayout包装了我的回收视图,现在它就像一个符咒。如中所述,此“问题”是线性布局中的故意行为,不会被修复。因此,如果可能的话,只需将您的RecyclerView包装如下:

<RelativeLayout
    android:id="@+id/container_messages_list"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:background="@drawable/chat_back_pattern"
    app:layout_constraintBottom_toTopOf="@+id/bottom_view"
    app:layout_constraintTop_toBottomOf="@+id/toolbar">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/messages_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
</RelativeLayout>


如果您使用
NestedScrollView
作为
RecyclerView
的父视图,那么延迟的答案总比没有好。您应该删除它。

我遇到了类似的问题,我尝试了上面列出的所有解决方案,但没有一个有效。 我已经将“有效载荷”填充为“notifyItemChanged(position,Payloads)”,因为我只需要“上传”一个复选框值,所以我在“有效载荷”中传递该值,而不调用整个viewholder的更新。 此解决方案适用于我的recycler视图中除最后一个之外的所有视图持有者(可能适用于所有“回收”的视图持有者,我指的是那些通过“回收”现有视图来回忆“onBindViewHolder”的视图持有者)。 我认为如果您只有recyclerview,那么使用“notifyItemChanged”将有效,我还认为嵌套的滚动视图和回收器视图会引发“自动滚动”问题

我在案件中被“raed”曝光,所以“ScroolView->
setAutoMeasureEnabled(false);
<RelativeLayout
    android:id="@+id/container_messages_list"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:background="@drawable/chat_back_pattern"
    app:layout_constraintBottom_toTopOf="@+id/bottom_view"
    app:layout_constraintTop_toBottomOf="@+id/toolbar">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/messages_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
</RelativeLayout>
msvContainer.onStopNestedScroll(mRecyclerView);
msvContainer.stopNestedScroll();