【问题标题】:How to update a specific TextView of an item in the RecyclerView?如何更新 RecyclerView 中某个项目的特定 TextView?
【发布时间】:2020-12-15 13:33:48
【问题描述】:

当用户点击另一个项目时,我想在我的 RecyclerView 中更新之前的 TextView 项目:

例如,如果用户点击“lemanju”TextView,它会将字体颜色变为橙色,当用户点击“Lightning”TextView时,lemanju的字体颜色应该变回黑色,而Lighning的字体颜色必须变为橙色,如下所示。

lemanju being selected

Lightning being selected (How I expect it to work)

Lightning being selected (What is happening now -> not updating lemanju's font color back to black)

我在我的适配器类中尝试了以下代码来实现这个结果:

// set previous item TextColor to black.
 holder.itemView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
 holder.adapter.notifyItemChanged(previousSamplePosition);

 // set actual item TextColor to orange.
 holder.itemView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));

不幸的是,当我点击 Lightning 时,我无法将 lemanju 的字体颜色改回黑色...

有谁知道如何使用 notifyItemChanged 更改特定的 TextView?或者有其他方法可以实现吗?

我的适配器类中的 onCreateViewHolder 方法,您可以在下面看到:

/**
     * Sets the contents of an item at a given position in the RecyclerView.
     * Called by RecyclerView to display the data at a specificed position.
     *
     * @param holder         The view holder for that position in the RecyclerView.
     * @param samplePosition The position of the item in the RecyclerView.
     *                       <p>
     */
    @Override
    public void onBindViewHolder(@NonNull SampleViewHolder holder, int samplePosition) {

        if (sampleList  != null) {
            Sample currentSample = sampleListFiltered.getCurrentList().get(samplePosition);
            // Add the data to the view holder.
            holder.sampleView.setText(currentSample.getName());
            holder.bind(currentSample);

            if (sampleNameSearched != null) {

                String sampleName = Normalizer.normalize(sampleListFiltered.getCurrentList().get(samplePosition).getName(), Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "").toLowerCase();
                Pattern sampleQuery = Pattern.compile(sampleNameSearched);
                Matcher sampleMatcher = sampleQuery.matcher(sampleName);
                SpannableStringBuilder spanString = new SpannableStringBuilder(sampleListFiltered.getCurrentList().get(samplePosition).getName());

                while (sampleMatcher.find()) {
                    spanString.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), sampleMatcher.start(), sampleMatcher.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                }
                holder.sampleView.setText(spanString);
            } else {
                // This solved the problem
                holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
            }
        }

        Bundle sampleBundle = new Bundle();

        holder.sampleView.setOnClickListener(view -> {
            sampleBundle.putLong("Sample", sampleListFiltered.getCurrentList().get(samplePosition).getId());
            SampleCollectorListNavigatorFragment.addScreenToStack(0);
            SampleCollectorListNavigatorFragment.setLastSurveyIdAccessed(sampleListFiltered.getCurrentList().get(samplePosition).getSurveyId());
            Navigation.findNavController(view).navigate(R.id.action_sampleCollectorListNavigator_to_sampleCollectorInspectSampleFragment, sampleBundle);
        });

        holder.sampleView.setOnLongClickListener(view -> {

            sampleBundle.putLong("Sample", sampleListFiltered.getCurrentList().get(samplePosition).getId());

            if (sampleID == 0) {
                // Access the view of the previous screen
                ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.VISIBLE);
                holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));
            } else if (sampleID == sampleListFiltered.getCurrentList().get(samplePosition).getId()) {
                if (((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).getVisibility() == View.VISIBLE) {
                    ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.GONE);
                    holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
                } else {
                    ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.VISIBLE);
                    holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));
                }
            } else if (sampleID != sampleListFiltered.getCurrentList().get(samplePosition).getId()) {
                holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
                notifyItemChanged(previousSamplePosition);
                holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));
                ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.VISIBLE);
            }

            sampleID = sampleListFiltered.getCurrentList().get(samplePosition).getId();
            previousSamplePosition = samplePosition;

            return true;
        });
    }
}

更新 -> 如何解决这个问题?

为了解决我的代码中的问题,我必须在我的搜索过滤器中将字符串更新回黑色:

// This solved the problem         
holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));

但是如果你没有和我一样的结构,或者你只是想更新回收器中之前的 TextView 项,你可以使用这部分代码:

holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
notifyItemChanged(previousSamplePosition);

notifyItemChanged(previousSamplePosition) 可以解决问题。

【问题讨论】:

    标签: android android-layout android-recyclerview


    【解决方案1】:

    这是一个基本示例,下面我也添加了您的代码

    你的适配器

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
        
        
        private String[] mDataset;
        List<TextView> textViews = new ArrayList<>();
        
        
        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder
        public static class MyViewHolder extends RecyclerView.ViewHolder {
            // each data item is just a string in this case
            public TextView textView;
            public MyViewHolder(TextView v) {
                super(v);
                textView = v.findViewById(R.id.textView);
            }
        }
        
        public MyAdapter(String[] myDataset) {
            mDataset = myDataset;
        }
    
        @Override
        public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                       int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.my_text_view, parent, false);
           
            MyViewHolder vh = new MyViewHolder(v);
            return vh;
        }
    
        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            holder.textView.setText(mDataset[position]);
            views.add(holder.textView);
    
        }
    
        @Override
        public int getItemCount() {
            return mDataset.length;
        }
        
        public List<TextView> getTextViews(){
            return textViews;
        }
    }
    

    您的活动

    public class MainActivity extends AppCompatActivity {
        
        private Button changeColorButton;
        private RecyclerView recyclerView;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            changeColorButton = findViewById(R.id.button);
            recyclerView = findViewById(R.id.recyclerView);
            
            MyAdapter adapter = new MyAdapter(new String[]{"Hello", "world"});
            recyclerView.setAdapter(adapter);
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
            
            changeColorButton.setOnClickListener(new OnClickListener() {
     
                @Override
                public void onClick(View view) {
                    int length = adapter.getTextViews().size();
                    List<TextView> textViews = adapter.textViews;
                    
                    for(int i=0; i<length; i++){
                        textViews.get(i).setTextColor(Color.parseColor("#bdbdbd"));
                    }
                }
     
            });
        }
    }
    

    现在你的代码

    public static class SampleViewHolder extends RecyclerView.ViewHolder {
    
            private final TextView sampleView;
    
            /**
             * Creates a new custom view holder to hold the view to display in the RecyclerView.
             *
             * @param sampleListView The view in which to display the data.
             * @param adapter        The adapter that manages the the data and views for the RecyclerView.
             */
            public SampleViewHolder(View sampleListView) {
                super(sampleListView);
                sampleView = sampleListView.findViewById(R.id.data_name);
            }
        }
    
        /**
         * Inflates an item view and returns a new view holder that contains it.
         * Called when the RecyclerView needs a new view holder to represent an item.
         *
         * @param parent   The view group that holds the item views.
         * @param viewType Used to distinguish views, if more than one type of item view is used.
         * @return a view holder.
         */
        @NonNull
        @Override
        public SampleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // Inflate an item view.
            View sampleListView = inflater.inflate(R.layout.fragment_sample_collector_list_sample, parent, false);
            return new SampleViewHolder(sampleListView);
        }
    
        /**
         * Sets the contents of an item at a given position in the RecyclerView.
         * Called by RecyclerView to display the data at a specificed position.
         *
         * @param holder         The view holder for that position in the RecyclerView.
         * @param samplePosition The position of the item in the RecyclerView.
         *                       <p>
         *                       TODO: Most important method used
         */
        @Override
        public void onBindViewHolder(@NonNull SampleViewHolder holder, int samplePosition) {
    
            if (sampleList != null) {
                // Retrieve the data for that position.
                //Sample currentSample = sampleListFiltered.get(samplePosition);
                Sample currentSample = sampleListFiltered.getCurrentList().get(samplePosition);
                // Add the data to the view holder.
                holder.sampleView.setText(currentSample.getName());
                holder.bind(currentSample);
                list.add(holder.sampleView);
    
                if (sampleNameSearched != null) {
    
                    String sampleName = Normalizer.normalize(sampleListFiltered.getCurrentList().get(samplePosition).getName(), Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "").toLowerCase();
                    Pattern sampleQuery = Pattern.compile(sampleNameSearched);
                    Matcher sampleMatcher = sampleQuery.matcher(sampleName);
                    SpannableStringBuilder spanString = new SpannableStringBuilder(sampleListFiltered.getCurrentList().get(samplePosition).getName());
    
                    while (sampleMatcher.find()) {
                        spanString.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), sampleMatcher.start(), sampleMatcher.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                    }
                    holder.sampleView.setText(spanString);
                }
            }
    
            Bundle sampleBundle = new Bundle();
            holder.sampleView.setOnClickListener(view -> {
                sampleBundle.putLong("Sample", sampleListFiltered.getCurrentList().get(samplePosition).getId());
                SampleCollectorListNavigatorFragment.addPreviousScreen(0);
                SampleCollectorListNavigatorFragment.setLastSurveyIdAccessed(sampleListFiltered.getCurrentList().get(samplePosition).getSurveyId());
                Navigation.findNavController(view).navigate(R.id.action_sampleCollectorListNavigator_to_sampleCollectorInspectSampleFragment, sampleBundle);
            });
    
            holder.sampleView.setOnLongClickListener(view -> {
    
                sampleBundle.putLong("Sample", sampleListFiltered.getCurrentList().get(samplePosition).getId());
    
                // TODO: if the same button is clicked close the buttonPanel, else keep it open.
                if (sampleID == 0) {
                    // Access the view of the previous screen
                    ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.VISIBLE);
                    holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));
                } else if (sampleID == sampleListFiltered.getCurrentList().get(samplePosition).getId()) {
                    if (((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).getVisibility() == View.VISIBLE) {
                        ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.GONE);
                        holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
                    } else {
                        ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.VISIBLE);
                        holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));
                    }
                } else if (sampleID != sampleListFiltered.getCurrentList().get(samplePosition).getId()) {
                    Toast.makeText(inflater.getContext(), "list size() " + list.size(), Toast.LENGTH_SHORT).show();
                    // I CANNOT CHANGE THE COLOR OF THE PREVIOUS SAMPLE RIGHT HERE.
                    List<RecyclerView.ViewHolder> vh = getItem();
                    changeColor(vh,previousSamplePosition);
                    holder.adapter.notifyItemChanged(previousSamplePosition);
                    holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.PrimaryColor_1));
                    ((Activity) inflater.getContext()).findViewById(R.id.ButtonPanel).setVisibility(View.VISIBLE);
                }
    
                sampleID = sampleListFiltered.getCurrentList().get(samplePosition).getId();
                previousSamplePosition = samplePosition;
    
                return true;
            });
        }
    
        public List<RecyclerView.ViewHolder> getItem(){
            return list;
        }
    
        public void changeColor(List<RecyclerView.ViewHolder> vh, int previousSamplePosition) {
            for (int i = 0; i < list.size(); i++) {
                if(i == previousSamplePosition) {
                    // Does not change the previous TextView.
                    Toast.makeText(inflater.getContext(), "i -> " + i + " previousSamplePos -> " + previousSamplePosition, Toast.LENGTH_SHORT).show();
                    // How can I use the vh here?
                    //vh.get(i).setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1));
                    //holder.adapter.notifyItemChanged(i);
                }
            }
        }
    }
    

    让我知道它是否有效

    【讨论】:

    • 我的适配器中有所有这些结构,但是我应该在 changeColor 函数中添加什么来更改特定的 TextView 项颜色?我的意思是...如何更改适配器列表的特定项目?我将添加我的 CreateViewHolder,这样你就可以看到我在做什么......
    • TextView 文本; public ViewHolder(@NonNull View itemView) { super(itemView);文本 = itemView.findViewById(R.id.theID); } 公共 changeColor(){ text.setTextColor(Color.parseColor("#bdbdbd")); } }参考这个链接看看怎么改变textVIew的颜色stackoverflow.com/questions/8472349/…
    • 是的,我已经在代码中使用了它,但是如何更新我点击的上一个项目?就像,我怎样才能更新以前的 TextView:// 这里......如何从以前的颜色更改并更新它? holder.sampleView.setTextColor(ContextCompat.getColor(inflater.getContext(), R.color.BaseColor_1)); holder.adapter.notifyItemChanged(previousSamplePosition);
    • 在我的回答中,看看最后的 2 个代码 sn-ps,一种存储所有元素的方法和一个改变每个元素颜色的循环。
    • getItem() 中的 viewHolders 返回变量是列表(您创建的 list)还是 ViewHolder 对象?
    猜你喜欢
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多