【问题标题】:How to change colors of parent Fragment and views of RecyclerView depending on OnClickListener position from recyclerview如何根据来自 recyclerview 的 OnClickListener 位置更改父 Fragment 和 RecyclerView 视图的颜色
【发布时间】:2024-12-19 18:40:02
【问题描述】:

这是一个困难的,所以我附上了一张图片来帮助形象化。

所以我有一个包含调色板的 recyclerview。它通过为每种颜色创建一个新的 ImageView 来加载颜色,然后更改每个图像视图的颜色和可绘制对象,为“选定颜色”设置不同的颜色。选择的颜色也用于从父DialogFragment更改工具栏的颜色。

问题在于,经过数小时的研究,OnClicklistener 根本不起作用。现在,我无法在应用程序崩溃的情况下使用 OnClickListener。

现在,让我们来看看实际的代码和问题。 我会(向你)声明一些我正在使用的变量和类:

ArrayList<String> colorsList = //arraylist which contains all the colors which can be displayed
NewNotebookFragment = //DialogFragment, contains a toolbar, miscellaneous views and a rvNewNotebook
RecyclerView rvNewNotebook = //the recyclerview containing imageviews representing each individual color retrieved from colorsList
NewNotebookAdapter = adapter which is bound to rvNewNotebook

现在,我所做的是在 NewNotebookFragment 中创建一个名为 changeColor 的方法,该方法可以接收一个 int,表示所选颜色的位置。 changeColor() 改变工具栏的颜色。从 OnclickListener 的 onClick 方法调用 changeColor(),在 NewNotebookAdapter 的 Viewholder 中定义。 现在是实际代码。

新笔记本片段:

public class NewNotebookFragment extends DialogFragment {

    RecyclerView rvNewNotebook;
    int activeColor;
    ArrayList<String> colors=Helpers.getPossibleColors();
    @Override
    public View onCreateView ...}
    @Override
    public void onViewCreated(View v, Bundle savedInstanceState){

        activeColor=new Random().nextInt(colors.size());

        toolbar = (Toolbar) v.findViewById(R.id.newnotebooktoolbar);
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                return false;
            }
        });
        toolbar.inflateMenu(R.menu.newnotebook);
        toolbar.setTitle("Create new Notebook");

        if(Helpers.isColorDark(Color.parseColor(colors.get(activeColor)))){
            toolbar.setTitleTextColor(getResources().getColor(R.color.md_dark_primary_text));
        }else{
            toolbar.setTitleTextColor(getResources().getColor(R.color.md_light_primary_text));
        }
        rvNewNotebook = (RecyclerView) v.findViewById(R.id.rvNewNotebook);
        final GridLayoutManager rvNotebookManager = new GridLayoutManager(getContext(),6);
        rvNewNotebook.setLayoutManager(rvNotebookManager);
        NewNotebookAdapter adapter= new NewNotebookAdapter(getContext(), Helpers.getPossibleColors(), activeColor);

        toolbar.setBackgroundColor(Color.parseColor(Helpers.getPossibleColors().get(activeColor)));
        rvNewNotebook.setAdapter(adapter);
        Log.d("onViewCreated", ""+rvNewNotebook.getWidth());


    }
    @Override public void onResume(){...}
    public static NewNotebookFragment newInstance() {...}

    public void changeColor(int position){
        if(Helpers.isColorDark(Color.parseColor(colors.get(position)))){
            toolbar.setTitleTextColor(getResources().getColor(R.color.md_dark_primary_text));
        }else{
            toolbar.setTitleTextColor(getResources().getColor(R.color.md_light_primary_text));
        }
        toolbar.setBackgroundColor(Color.parseColor(Helpers.getPossibleColors().get(position)));
    }

新笔记本适配器:

public class NewNotebookAdapter extends RecyclerView.Adapter<NewNotebookAdapter.ViewHolder>{
    Context context;
    ArrayList<String> colors = new ArrayList<>();
    int activeColor;
    public NewNotebookAdapter(){

    }

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        public ImageView ivSwatch;
        public Toolbar toolbar;
        public ViewHolder(View itemView) {
            super(itemView);
            ivSwatch = (ImageView) itemView.findViewById(R.id.ivSwatch);
            toolbar = (Toolbar) itemView.findViewById(R.id.newnotebooktoolbar);
            ivSwatch.setOnClickListener(this);
        }


        @Override
        public void onClick(View view) {
            NewNotebookFragment newNotebookFragment = new NewNotebookFragment();
            final int adapterPosition = ViewHolder.this.getAdapterPosition();
            Log.d("OnClick. Adapter", "getAdapterPosition: "+adapterPosition);
            newNotebookFragment.changeColor(adapterPosition);
        }
    }
    public NewNotebookAdapter(Context context, ArrayList<String> colors, int activeColor){
        this.context=context;
        this.colors=colors;
        this.activeColor=activeColor;
    }

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


    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        Drawable drawablefull = ContextCompat.getDrawable(context,R.drawable.colorcircle);
        Drawable drawableHollow = ContextCompat.getDrawable(context,R.drawable.coloroutlinecircle);
        if (position==activeColor){
            holder.ivSwatch.setImageDrawable(drawablefull.mutate());
        }else if (position!=activeColor){
            holder.ivSwatch.setImageDrawable(drawableHollow.mutate());
        }
        holder.ivSwatch.setColorFilter(Color.parseColor(colors.get(position)));

我目前的问题是以下堆栈跟踪:

FATAL EXCEPTION: main
                                                                                           Process: com.twotowerstudios.virtualnotebookdesign, PID: 32272
                                                                                           java.lang.IllegalStateException: Fragment NewNotebookFragment{b10003e} not attached to Activity
                                                                                               at android.support.v4.app.Fragment.getResources(Fragment.java:648)
                                                                                               at com.twotowerstudios.virtualnotebookdesign.NewNotebookDialog.NewNotebookFragment.changeColor(NewNotebookFragment.java:85)
                                                                                               at com.twotowerstudios.virtualnotebookdesign.NewNotebookDialog.NewNotebookAdapter$ViewHolder.onClick(NewNotebookAdapter.java:49)
                                                                                               at android.view.View.performClick(View.java)
                                                                                               at android.view.View$PerformClick.run(View.java)
                                                                                               at android.os.Handler.handleCallback(Handler.java)
                                                                                               at android.os.Handler.dispatchMessage(Handler.java)
                                                                                               at android.os.Looper.loop(Looper.java)
                                                                                               at android.app.ActivityThread.main(ActivityThread.java)
                                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
                                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
                                                                                               at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)

现在我几乎可以肯定这与我的 onClick 方法有关,它创建了一个 NewNotebookFragment 的新实例,导致我在 onClick 方法中使用的片段实际上与已经使用的片段不同并显示。但是,我正在制作这个线程,因为我对如何解决整个问题没有真正的想法。例如,我不知道如何从 onClick 方法中获取实际的 NewNotebookFragment,以便我可以修改它或从中调用方法。不知道有没有一次 如果它甚至可以工作或其他任何东西,它都已修复。我怎样才能让它工作?

编辑:我让它完美地工作。基本上我所做的是在 Imageviews 上的 onBindViewHolder 中定义 setonclickListener。 clickListener 将调用一个名为 AdapterInterface 的接口,并在其中使用一个名为 clickListener 的方法,它允许我将颜色的 int 传递给父片段。该片段将实现在适配器中定义的接口,并将覆盖 clickListener,使用传递给它的颜色并从中调用 changeColor 方法。如果将来有人需要示例,请随时与我联系。相关更改在这两个文件中,上传到 Github:https://gist.github.com/coldblade2000/0c2cac8b1af4df5985fe6cebebc9cff2 链接包含关于这两个类的一定程度的解释和文档

【问题讨论】:

    标签: android android-recyclerview fragment onclicklistener android-dialogfragment


    【解决方案1】:

    查看您的代码,每次单击它都会创建一个新片段。我相信您想要的是更改对话框片段工具栏的颜色。您可以做的第一件事是创建一个接口侦听器,作为对 Fragment 的回调,该回调将传递给 Adapter。像这样的

      public interface ViewHolderOnClickListener {
    
        //This method can be any parameters, I'm pasing color here since you need the color code
        public void onViewHolderClick(View itemView, int position, int color);
      }
    

    然后在您的适配器和 viewholder 构造方法中,添加一个接口实例作为您的参数。您可以直接在创建适配器时传递它,也可以让您的 Fragment 实现接口并使用“this”传递它

      public TempAdapter(ViewHolderOnClickListener viewHolderOnClickListener) {
        this.viewHolderOnClickListener = viewHolderOnClickListener;
      }
    

    在您的 ViewHolder 中,使用

    进行回调
    @Override
    public void onClick(View view) {
      viewHolderOnClickListener.onViewHolderClick(*PARAMS HERE*);
    }
    

    这样,您的片段可以侦听在您的 ViewHolder 中发生的 OnClick,并做出相应的响应。

    另一种方法是使用EventBuses

    【讨论】:

    • 我不在我的电脑前,但我想你只是用界面引导我走上了正确的轨道。大约是时候我知道它们是什么了。完成后,我将发布我的固定代码。虽然我不是很明白。我怎样才能改变 recyclerview 孩子呢?我会用与我的片段不同的 activeColor 销毁并重新创建 recyclerview 吗?
    • 您可以从附加的 ArrayList 中删除/更改子索引,在您的情况下为颜色,并使用 notifyItemRemoved() 或 notifyItemChanged() 来更新回收站视图。或者,如果您的整个颜色数据数组列表发生了变化,请使用 notifyDataSetChanged()
    最近更新 更多