Reputation: 1093
I have a recyclerView with n items. Each item is expandable onCLick of it. I want my item to expand as well as move to the top onCLick. Suppose if I click third item then it should move to the first item position and then it will expand and scroll should stop. I have manage to expand the RecyclerView with animation, but it's not moving at the top position. I also tried scrollToPosition, but it didn't work. Below is my Activity class:
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
ArrayList<Integer> catImg=new ArrayList<>();
private CategoryAdapter mAdapter;
RecyclerView.LayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
catImg.add(R.drawable.eyebrowposition_wide);
catImg.add(R.drawable.eyebrowthickness_question);
catImg.add(R.drawable.eyebrowthickness_thick);
catImg.add(R.drawable.eyebrowthickness_thin);
mAdapter = new CategoryAdapter(this,catImg);
recyclerView.setHasFixedSize(true);
// vertical RecyclerView
// keep movie_list_row.xml width to `match_parent`
mLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false);
// horizontal RecyclerView
// keep movie_list_row.xml width to `wrap_content`
// RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(mLayoutManager);
// adding inbuilt divider line
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
// adding custom divider line with padding 16dp
// recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
}
public void setRecyclerViewScroll(final int rowDistance) {
new Handler().postDelayed(new Runnable() {
public void run() {
// do something...
mLayoutManager.smoothScrollToPosition(recyclerView, null, 1);
}
}, 100);
}
}
Adapter class:
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.MyViewHolder>{
private ArrayList<Integer> catList;
Context mctx;
private int originalHeight = 0;
public CategoryAdapter(Context mctx, ArrayList<Integer> catList) {
this.catList = catList;
this.mctx = mctx;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.custom_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.img_cat.setBackgroundResource(catList.get(position));
}
@Override
public int getItemCount() {
return catList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView title, year, genre;
private boolean mIsViewExpanded = false;
public ImageView img_cat;
public LinearLayout lin2;
public MyViewHolder(View view) {
super(view);
img_cat = view.findViewById(R.id.img_cat);
lin2= view.findViewById(R.id.lin2);
if (mIsViewExpanded == false) {
// Set Views to View.GONE and .setEnabled(false)
lin2.setVisibility(View.GONE);
lin2.setEnabled(false);
}
img_cat.setOnClickListener(this);
}
@Override
public void onClick(final View view) {
// If the originalHeight is 0 then find the height of the View being used
// This would be the height of the cardview
if (originalHeight == 0) {
originalHeight = view.getHeight();
}
// Declare a ValueAnimator object
ValueAnimator valueAnimator;
if (!mIsViewExpanded) {
lin2.setVisibility(View.VISIBLE);
lin2.setEnabled(true);
mIsViewExpanded = true;
valueAnimator = ValueAnimator.ofInt(originalHeight, 600); // These values in this method can be changed to expand however much you like
int rowHeightFromStart = (getAdapterPosition()) *40;
((MainActivity)mctx).setRecyclerViewScroll(rowHeightFromStart);
} else {
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(originalHeight + (int) (originalHeight * 2.0), originalHeight);
Animation a = new AlphaAnimation(1.00f, 0.00f); // Fade out
a.setDuration(200);
// Set a listener to the animation and configure onAnimationEnd
a.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
lin2.setVisibility(View.GONE);
lin2.setEnabled(false);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
// Set the animation on the custom view
lin2.startAnimation(a);
}
valueAnimator.setDuration(200);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
lin2.getLayoutParams().height = value.intValue();
lin2.requestLayout();
}
});
valueAnimator.start();
}
}
}
How can I shift my clicked item to the top position. What I am doing wrong?
Upvotes: 3
Views: 7919
Reputation: 557
Moving to the top? Sure! 🙋♀️
This creates a nice animation with Kotlin, rendering the scrolling invisible to the eye:
In the Adapter:
Collections.swap(list, fromPosition, 0)
notifyItemMoved(fromPosition, 0)
// TODO: Callback to the fragment through listener or ViewModel
In the Fragment:
recyclerView.layoutManager?.scrollToPosition(0)
Cheers!
Upvotes: 3
Reputation: 880
You can do like this way: Create one method in adaptor as below.
public void swapeItem(int fromPosition,int toPosition){
Collections.swap(arrayList, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
now on item click you can use like this way.
swapeItem(9,0); // here 9 is a clicked item position and 0 means at top of the list.
Upvotes: 9