• Android-----RecyclerView嵌套Spinner onItemSelected问题


    在使用RecyclerView嵌套Spinner时会出现这样一个问题:改变第一个spinner的值时,下面有些隐藏的spinner的选项也跟着改变,然后我又往上拉,刚刚选的又改变,重复操作,隐藏起来的每次都会变

    分析了一下原因:如果一页显示10个item,第一个滚不见了,第十一个出现的时候,可能复用的第一个item,如果不重新设置监听,spinner选择改变的是第一个itemi的选择。并且每次onBindViewHolder的时候,标题和spinner的属性都需要重新设置

    第一种解决方法:继承spinner,在spinner中做一些操作

    package com.org.youtu;
    
    import android.annotation.TargetApi;
    import android.content.Context;
    import android.content.res.Resources;
    import android.os.Build;
    import android.support.v7.widget.AppCompatSpinner;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.Spinner;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * Created by Administrator on 2020/9/10.
     */
    
    public class MySpinnerView extends AppCompatSpinner {
    
        private ItemClick mItemClick;
    
    
    
        public MySpinnerView(Context context) {
            super(context);
            init();
        }
    
        public MySpinnerView(Context context, int mode) {
            super(context, mode);
            init();
        }
    
        public MySpinnerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public MySpinnerView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        public MySpinnerView(Context context, AttributeSet attrs, int defStyleAttr, int mode) {
            super(context, attrs, defStyleAttr, mode);
            init();
        }
    
        public MySpinnerView(Context context, AttributeSet attrs, int defStyleAttr, int mode, Resources.Theme popupTheme) {
            super(context, attrs, defStyleAttr, mode, popupTheme);
            init();
        }
    
        @TargetApi(Build.VERSION_CODES.KITKAT)
        private void init() {
            Class<?> myClass = Spinner.class;
            try {
                Class<?>[] params = new Class[1];
                params[0] = OnItemClickListener.class;
                Method m = myClass.getDeclaredMethod("setOnItemClickListenerInt", params);
                m.setAccessible(true);
                m.invoke(this, new OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        Class<?> myClass = AdapterView.class;
                        try {
                            Field field = myClass.getDeclaredField("mOldSelectedPosition");
                            field.setAccessible(true);                                          //设置mOldSelectedPosition可访问
                            field.setInt(MySpinnerView.this, AdapterView.INVALID_POSITION);     //设置mOldSelectedPosition的值
    
                            mItemClick.onClick(position);
    
                        } catch (NoSuchFieldException | IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                });
            } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    
        public void setItemClick(ItemClick itemClick){
            this.mItemClick = itemClick;
        }
    
        public interface ItemClick {
            void onClick(int position);
        }
    
    }

    在子项布局中使用:

    <?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="50dp"
        android:gravity="center"
        android:background="@color/colorPrimary"
        android:orientation="horizontal">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
    
            <TextView
                android:id="@+id/textview"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:layout_marginLeft="25dp"
                android:text=""
                android:textSize="18sp"
                android:textColor="#ffffff"/>
    
            <com.org.youtu.MySpinnerView
                android:id="@+id/spinnerSel"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:entries="@array/spinnerVal">
    
            </com.org.youtu.MySpinnerView>
    
        </LinearLayout>
    
    
    
    </LinearLayout>

    适配器中:

    package com.org.youtu.Adapter;
    
    import android.graphics.Color;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.LinearLayout;
    import android.widget.Spinner;
    import android.widget.TextView;
    
    import com.org.youtu.MySpinnerView;
    import com.org.youtu.R;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by Administrator on 2020/9/7.
     */
    
    public class recyclerViewAdapter extends RecyclerView.Adapter<recyclerViewAdapter.viewHolder> implements View.OnClickListener{
    
        public static String [] Groups = {"车辆唯一性检查","车辆特征参数检查","车辆外观检查","安全装置检查"};
        public static String [] AJCheckContens = {
                "号牌号码/车辆类型","车辆品牌/型号","车辆识别代号(或整车出厂编号)","发动机号码(或电动机号码)","车辆颜色和形状",
                "核定载人数","核定载质量",
                "车身外观","外观标识、标注和标牌","外部照明和信号灯具","轮胎","号牌和号码安装","加装/改装灯具",
                "汽车安全带","机动车用三角警告牌","灭火器","行驶记录装置","车身反光标识",
        };
    
        public Map<String , String> map = null;
    
        public RecyclerView recyclerView;
    
        private RVItemClickListener rvClickListener = null;
    
        private viewHolder holder = null;
    
        public void setRecyclerViewClickListener(RVItemClickListener recyclerViewListener){
            this.rvClickListener = recyclerViewListener;
        }
    
    
        public recyclerViewAdapter(RecyclerView rv){
            map = new HashMap<>();
            for (int i = 0 ; i< AJCheckContens.length ; i ++){
                map.put(i+"","1");
                Log.e("map中的数据",map.get(i+"") + "		map的长度:		"+ map.size());
            }
            this.recyclerView = rv;
        }
    
        @Override
        public viewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.tab_item_view,parent,false);
            view.setOnClickListener(this);
            holder = new viewHolder(view);
            return holder;
        }
    
        @Override
        public void onBindViewHolder(final viewHolder holder, final int position) {
            holder.listCarID.setText(AJCheckContens[position]);
            holder.spinner.setItemClick(new MySpinnerView.ItemClick() {
                @Override
                public void onClick(int position) {
                    Log.e("spinner设置点击监听","监听点击成功");
                }
            });
            holder.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    LinearLayout layout = (LinearLayout) view.getParent().getParent();          //通过spinner组件选项拿到父组件Layout
                    TextView textView = (TextView) layout.getChildAt(0);                     //通过父组件拿到子组件TextView
                    TextView selectVal = (TextView) view;                                       //选中的值
                    Log.e("选中的值",selectVal.getText()+"	选项:	" + textView.getText());
    
    
                    holder.update(textView.getText().toString(),position);
    
    
                    for (int n = 0 ; n < AJCheckContens.length ; n ++){
                        if (AJCheckContens[n].equals(textView.getText().toString().trim())){
                            if (selectVal.getText().equals("不合格")){
                                map.put(n+"","0");
                            }else {
                                map.put(n+"","1");
                            }
                            Log.e("字段所在位置",(n+1) + "	map的key值:	" + getMapKey(textView.getText().toString()) +"	改变后的值:	" + map.get(n+""));
                            break;
                        }
                    }
                }
    
                @Override
                public void onNothingSelected(AdapterView<?> parent) {
    
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return AJCheckContens.length;
        }
    
    
    
        @Override
        public void onClick(View view) {
    
            if (rvClickListener != null){
                int position = recyclerView.getChildAdapterPosition(view);
                rvClickListener.onItemClick(recyclerView,view,position,AJCheckContens[position]);
            }
    
        }
    
        /**【定义一个内部类,展示的数据由内部类决定】**/
        static class viewHolder extends RecyclerView.ViewHolder{
            private TextView listCarID;
            private MySpinnerView spinner;
            public viewHolder(View view) {
                super(view);
                listCarID = view.findViewById(R.id.textview);
                spinner = view.findViewById(R.id.spinnerSel);
            }
    
            public void update(String title , int position){
                listCarID.setText(title);
                spinner.setSelection(position);
                spinner.setItemClick(new MySpinnerView.ItemClick() {
                    @Override
                    public void onClick(int position) {
                        Log.e("更新监听","监听更新成功");
                    }
                });
            }
        }
    }

    然后在Activity中:

    package com.org.youtu;
    
    import android.graphics.Color;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.gavin.com.library.StickyDecoration;
    import com.gavin.com.library.listener.GroupListener;
    import com.org.youtu.Adapter.RVItemClickListener;
    import com.org.youtu.Adapter.recyclerViewAdapter;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class recyclerViewActivity extends AppCompatActivity {
    
        RecyclerView recyclerViewUse;
        Button start , commit;
        recyclerViewAdapter adapter;
    
        public static String [] Groups = {"车辆唯一性检查","车辆特征参数检查","车辆外观检查","安全装置检查"};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.recycler_view);
    
            recyclerViewUse = findViewById(R.id.recyclerViewUse);
    
            GroupListener groupListener = new GroupListener() {
                @Override
                public String getGroupName(int position) {
                    return groupName(position);
                }
            };
    
            StickyDecoration decoration = StickyDecoration.Builder.init(groupListener)
                    .setGroupHeight(40).setGroupTextSize(15).build();
    
            LinearLayoutManager manager = new LinearLayoutManager(this);
            recyclerViewUse.setLayoutManager(manager);
            recyclerViewUse.addItemDecoration(decoration);
    
            adapter = new recyclerViewAdapter(recyclerViewUse);
            adapter.setRecyclerViewClickListener(new RVItemClickListener() {
                @Override
                public void onItemClick(RecyclerView parent, View view, int position, String data) {
                    //view.setBackgroundColor(Color.GREEN);
                    TextView textView = (TextView) view.findViewById(R.id.textview);
                    textView.setTextColor(Color.RED);
                    Log.e("点击的位置","		" + position + "	数据:	" + data);
                }
            });
            recyclerViewUse.setAdapter(adapter);
    
            start = findViewById(R.id.Start);
            commit = findViewById(R.id.Commit);
            start.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    LogMapInfo(adapter.map);
                }
            });
    
            commit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                }
            });
    
        }
    
        public String groupName(int position){
            if (position == 0){
                return "车辆唯一性检查";
            }else if (position == 5){
                return "车辆特征参数检查";
            }else if (position == 7){
                return "车辆外观检查";
            }else if (position == 13){
                return "安全装置检查";
            }else {
                return null;
            }
    
        }
    
        //打印map中的内容
        public void LogMapInfo(Map<String , String> map){
            for (int i = 1;i<map.size();i++){
                try {
                    Thread.sleep(1000);
                    Log.e("打印内容",map.get(""+i) +"		" + System.currentTimeMillis());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }
    
    }

    运行效果图:某些手机上可以,但是在我的手机上却是没有作用,所以我换了一种方法来实现

    第二种方法:使用textView来替代spinner、因为我这里是只有两个选项,所以我直接用最简单的方式来实现、若要实现下拉效果,可以使用popupWindow,或者使用弹出框来替代

    text view实现方式:子项布局

    <?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="80dp"
        android:gravity="center"
        android:orientation="horizontal">
    
        <TextView
            android:id="@+id/textTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            />
    
        <TextView
            android:id="@+id/textResult"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />
    
    </LinearLayout>

    主体布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.org.youtu.recyclerViewActivity">
    
    
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
    
    
                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerViewUse"
                    android:layout_width="match_parent"
                    android:layout_marginBottom="50dp"
                    android:layout_height="wrap_content">
    
                </android.support.v7.widget.RecyclerView>
    
    
    
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_alignParentBottom="true">
    
                <Button
                    android:id="@+id/Start"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:text="检验开始" />
    
                <Button
                    android:id="@+id/Commit"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="10dp"
                    android:text="提交数据"/>
    
            </LinearLayout>
        </RelativeLayout>
    
    </LinearLayout>

    适配器:adapter

    package com.org.youtu.Adapter;
    
    import android.graphics.Color;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import com.org.youtu.R;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * Created by Administrator on 2020/9/10.
     */
    
    public class MyTextAdapter extends RecyclerView.Adapter<MyTextAdapter.viewHolder>{
    
    
        private MyTextAdapter.viewHolder holder = null;
        private List<checkResult> resultList;
        public Map<String , String> map;
    
        public MyTextAdapter(List<checkResult> list){
           this.resultList = list;
           map = new HashMap<>();
           for (int i = 0 ; i < list.size(); i ++){
               map.put(""+i,"1");
           }
    
        }
    
    
        @Override
        public viewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_item,parent,false);
            holder = new viewHolder(view);
            return holder;
        }
    
        @Override
        public void onBindViewHolder(final viewHolder holder,final int position) {
            if (resultList.get(position).isCheck()){
                holder.result.setText("合格");
                holder.result.setTextColor(Color.GREEN);
            }else {
                holder.result.setText("不合格");
                holder.result.setTextColor(Color.RED);
            }
            holder.title.setText(resultList.get(position).getTitle());
            holder.result.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.e("position的值为","		"+position);
                    if (resultList.get(position).isCheck()){
                        holder.result.setText("不合格");
                        holder.result.setTextColor(Color.RED);
                        resultList.get(position).setCheck(false);
                        map.put(""+position,"0");
                    }else {
                        holder.result.setText("合格");
                        holder.result.setTextColor(Color.GREEN);
                        resultList.get(position).setCheck(true);
                        map.put(""+position,"1");
                    }
                }
            });
        }
    
    
        @Override
        public int getItemCount() {
            return resultList.size();
        }
    
    
        static class viewHolder extends RecyclerView.ViewHolder {
            private TextView title , result;
    
            public viewHolder(View view) {
                super(view);
                title = view.findViewById(R.id.textTitle);
                result = view.findViewById(R.id.textResult);
            }
        }
    
    }

    实体类:checkResult

    package com.org.youtu.Adapter;
    
    /**
     * Created by Administrator on 2020/9/10.
     */
    
    public class checkResult {
    
        private String title;
        private String result;
        private boolean isCheck;
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getResult() {
            return result;
        }
    
        public void setResult(String result) {
            this.result = result;
        }
    
        public boolean isCheck() {
            return isCheck;
        }
    
        public void setCheck(boolean check) {
            isCheck = check;
        }
    }

    Activity中处理代码:

    package com.org.youtu;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import com.gavin.com.library.StickyDecoration;
    import com.gavin.com.library.listener.GroupListener;
    import com.org.youtu.Adapter.MyTextAdapter;
    import com.org.youtu.Adapter.checkResult;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class recyclerViewTextView extends AppCompatActivity {
    
        public static String [] AJCheckContens = {
                "号牌号码/车辆类型","车辆品牌/型号","车辆识别代号(或整车出厂编号)","发动机号码(或电动机号码)","车辆颜色和形状",
                "核定载人数","核定载质量",
                "车身外观","外观标识、标注和标牌","外部照明和信号灯具","轮胎","号牌和号码安装","加装/改装灯具",
                "汽车安全带","机动车用三角警告牌","灭火器","行驶记录装置","车身反光标识",
        };
    
    
        private RecyclerView textRecyclerView;
        private Button textStart , textCommit;
        private List<checkResult> list;
        private MyTextAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_recycler_view_text_view);
    
            init();
        }
    
        private void init(){
    
            list = new ArrayList<>();
    
            for (int i = 0 ; i< AJCheckContens.length ; i ++){
                checkResult result = new checkResult();
                result.setTitle(AJCheckContens[i]);
                result.setResult("合格");
                result.setCheck(true);
                list.add(result);
            }
    
            textRecyclerView = findViewById(R.id.textRecyclerView);
    
            GroupListener groupListener = new GroupListener() {
                @Override
                public String getGroupName(int position) {
                    return groupName(position);
                }
            };
            StickyDecoration decoration = StickyDecoration.Builder.init(groupListener)
                    .setGroupHeight(40).setGroupTextSize(15).build();
    
            LinearLayoutManager manager = new LinearLayoutManager(this);
    
            textRecyclerView.setLayoutManager(manager);
    
            textRecyclerView.addItemDecoration(decoration);
    
    
            adapter = new MyTextAdapter(list);
            textRecyclerView.setAdapter(adapter);
    
            textStart = findViewById(R.id.textStart);
            textStart.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                }
            });
            textCommit = findViewById(R.id.textCommit);
            textCommit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    for (int n = 0; n < adapter.map.size() ; n ++){
                        Log.e("map中的值",adapter.map.get(n+"") + "	n的值:	" + n);
                    }
                }
            });
        }
    
        public String groupName(int position){
            String name = null;
            if (position == 0){
                name = "车辆唯一性检查";
                return name;
            }else if (position == 5){
                name = "车辆特征参数检查";
                return name;
            }else if (position == 7){
                name = "车辆外观检查";
                return name;
            }else if (position == 13){
                name = "安全装置检查";
                return name;
            }else{
                return null;
            }
    
        }
    }

    运行结果:隐藏再拉出之后,不会改变已选择的数据,只有点击的时候才会改变展示的结果

    最后提交map中的数据结果:正是我们选择的结果,至此大功告成。

  • 相关阅读:
    触发Full GC执行的情况 以及其它补充信息
    HotSpot垃圾收集器GC的种类
    JVM学习之GC常用算法
    十大经典排序算法
    Java transient关键字使用
    Java并发编程:volatile关键字解析
    Linux Centos7.2 编译安装PHP7.0.2
    深入理解分布式事务及高并发下分布式事务的解决方案
    Windows及Linux环境搭建Redis集群
    软件项目进度管理(含敏捷项目管理)
  • 原文地址:https://www.cnblogs.com/xiobai/p/13647084.html
Copyright © 2020-2023  润新知