Search code examples
androidandroid-recyclerviewandroid-imageviewandroid-custom-view

Setting CircularImageView border color programmatically


I am using the CircularImageView library. I have a CircularImageView in my ViewHolder, and I want to change its border color on click.

My onBindViewHolder:

public void onBindViewHolder(ThumbnailAdapter.ViewHolder holder, int position) {
        ... //getting the relevant user from dataset and other irrelevant stuff

        if(selectedUsers.size() == 0 || selectedUsers.contains(user)) {
            holder.thumbnail.setBorderColor(R.color.selected);
        } else {
            holder.thumbnail.setBorderColor(R.color.not_selected);
        }

        holder.thumbnail.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (selectedUsers.contains(user)) {
                    selectedUsers.remove(user);
                } else {
                    selectedUsers.add(user);
                }

                notifyDataSetChanged();
            }
        });
}

The weird thing is that the first coloring works (the border color is indeed not the one predefined in the xml), but any further change does not affect the view (though the event is called and the value is changed). I tried to change also the drawable to eliminate a RecyclerView-related problem, and it works as expected.

Am I doing anything wrong? Maybe there's a bug in the library (if so, I couldn't find it)? Any help will be appreciated!

EDIT: More adapter code:

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

static class ViewHolder extends RecyclerView.ViewHolder {
        CircularImageView thumbnail;

        ViewHolder(View v) {
            super(v);
            thumbnail = (CircularImageView) v.findViewById(R.id.user_thumbnail);
        }
    }

private List<User> mDataSet;
private List<User> selectedUsers;

public ThumbnailAdapter(List<User> dataSet) {
        mDataSet = dataSet;
        selectedUsers = new ArrayList<>();
    }

Setting the adapter:

        mAdapter = new ThumbnailAdapter(users);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
        mRecyclerView.setAdapter(mAdapter);

Solution

  • I got it working, try this:

    enter image description here

    public void onBindViewHolder(RecyclerView.ViewHolder mholder, int position) {
    
            final User user = mList.get(position);
    
    
            final ViewHolder holder = (ViewHolder) mholder;
    
            if(selectedUsers.size() == 0 || selectedUsers.contains(user))
            {
                //holder.thumbnail.setBorderColor(Color.GREEN);
    
                setBorder(holder.thumbnail, true);
            } else {
                //holder.thumbnail.setBorderColor(Color.RED);
                setBorder(holder.thumbnail, false);
    
            }
    
            holder.thumbnail.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (selectedUsers.contains(user)) {
                        selectedUsers.remove(user);
                    } else {
                        selectedUsers.add(user);
                    }
    
                    //notifyItemChanged(position);
                    notifyDataSetChanged();
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return mList.size();
        }
    
        public void setBorder(CircularImageView circularImageView, boolean selected) {
    
            // Set Border
            if(selected) {
                circularImageView.setBorderColor(context.getResources().getColor(R.color.colorPrimary));
                circularImageView.setBorderWidth(50);
                circularImageView.setBackgroundColor(0xffffffff);
            }
            else
            {
                circularImageView.setBorderColor(context.getResources().getColor(R.color.colorAccent));
                circularImageView.setBorderWidth(50);
                circularImageView.setBackgroundColor(0xffffffff);
            }
    // Add Shadow with default param
            //circularImageView.addShadow();
    // or with custom param
            //circularImageView.setShadowRadius(1);
            //circularImageView.setShadowColor(Color.WHITE);
        }
    

    Something else you should do for performance improvement: look inside your View.OnClickListener() switch the notifyDataSetChanged() which will force a complete full layout on the LayoutManager for the precision method notifyItemChanged(position); which will perform the task you want without redrawing everything

    Hope this helps! =)