Reputation: 600
I have two RecyclerViews in my app, and in both i use "SetClipToOutline" to get rounded corners / circular view on images. In one RecyclerView I get the desired effect. However, when I try to do the same for the other RecyclerView, it fails.
I will just show the code for the one where it doesn't work, and what I tried to make it work. Otherwise, there will be way too much code for you guys to read through.
My XML: `
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<ImageView
android:id="@+id/imageview_swipe_profile_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_marginBottom="10dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="@drawable/profile_photo_container"
app:layout_constraintDimensionRatio="h,3:4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
`
My RecyclerViewAdapter(java file):
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Collections;
public class SwipeAdapter extends RecyclerView.Adapter<SwipeAdapter.CustomViewHolder> {
private final Context context;
private ArrayList<SwipeMatchCandidate> candidates = new ArrayList<>();
SwipeAdapter(Context context) {
this.context = context;
}
@NonNull
@Override
public SwipeAdapter.CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
assert layoutInflater != null;
View v = layoutInflater.inflate(R.layout.swipe_one_profile_in_list, parent, false);
return new CustomViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull SwipeAdapter.CustomViewHolder holder, int position) {
// Sets rounded corners on the profile image. This doesn't work for some reason (maybe because
// clip is on the background and we set background to be the image.
// However, it is the correct code and should likely be under the OnBindViewHolder.
holder.profileImage.setClipToOutline(true);
SwipeMatchCandidate candidate = candidates.get(position);
holder.profileImage.setBackground(candidate.colors.get(0));
}
@Override
public int getItemCount() {
return candidates.size();
}
void addMatchCandidate(SwipeMatchCandidate swipeMatchCandidate) {
candidates.add(swipeMatchCandidate);
}
ItemTouchHelper.Callback createHelperCallback() {
/*
* First Param is for Up/Down motion, second is for Left/Right.
* Note that we can supply 0, one constant (e.g. ItemTouchHelper.LEFT), or two constants (e.g.
* ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) to specify what directions are allowed.
*/
return new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
//not used, as the first parameter above is 0
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int swipeDir) {
int position = viewHolder.getAdapterPosition();
candidates.remove(position);
notifyItemRemoved(position);
}
};
}
class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View profileImage;
CustomViewHolder(View itemView) {
super(itemView);
profileImage = itemView.findViewById(R.id.imageview_swipe_profile_container);
profileImage.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int pos = this.getAdapterPosition();
SwipeMatchCandidate candidate = candidates.get(pos);
Collections.rotate(candidate.colors, 1);
profileImage.setBackground(candidate.colors.get(0));
}
}
}
I assume it's in this Adapter that I use the SetClipToOutline method? That's what I did for the other RecyclerView when it worked.
Thanks for any help in advance.
Upvotes: 0
Views: 4521
Reputation: 83
You are changing the background of your view so it has different outline than you set before in xml (probably your rounded one). You can read more about clipping views and outline here: https://developer.android.com/training/material/shadows-clipping https://developer.android.com/reference/android/graphics/Outline#canClip()
Try to set ImageView content rather than background.
Consider using this:
@Override
public void onBindViewHolder(@NonNull SwipeAdapter.CustomViewHolder holder, int position) {
SwipeMatchCandidate candidate = candidates.get(position);
holder.profileImage.setImageDrawable(ColorDrawable(candidate.colors.get(0)));
}
Or if your colors collection is returning ColorDrawable instead of Color Int:
@Override
public void onBindViewHolder(@NonNull SwipeAdapter.CustomViewHolder holder, int position) {
SwipeMatchCandidate candidate = candidates.get(position);
holder.profileImage.setImageDrawable(candidate.colors.get(0));
}
Remember to add View.setClipToOutline()
in viewholder constructor.
Upvotes: 4