5

I am developing an app where there is a recyclerview with some cards and would like to create a zoom in effect when the user touches the card and zoom out when release the touch. The previous and next cards should respect the size of the card as it expands, not behind or forward

I would like to create something similar to this layout manager, but by touching the screen instead of scrolling.

   //RecyclerView
    recyclerView = view.findViewById(R.id.recyclerView)

    recyclerView.setHasFixedSize(false)

    recyclerView.layoutManager = CenterZoomLayoutManager(activity, LinearLayoutManager.VERTICAL, false)

How to create this effect? Thanks in advance.

Vitor Ferreira
  • 1,075
  • 1
  • 14
  • 28

3 Answers3

12

You can achieve something similar with stateListAnimator. In this example I attached stateListAnimator to recyclerView item. When item is pressed scale is 1, when not pressed scale is 0.8

result

recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/item_animal_height"
    android:background="#f00"
    android:stateListAnimator="@animator/list_animator"/>

res/animator/list_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:valueTo="1"/>

            <objectAnimator android:propertyName="scaleY"
                android:valueTo="1"/>
        </set>
    </item>
    <item
        android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:valueTo="0.8"/>

            <objectAnimator android:propertyName="scaleY"
                android:valueTo="0.8"/>
        </set>
    </item>
</selector>
ashakirov
  • 12,112
  • 6
  • 40
  • 40
0

Please use below code in onBindViewHolder to achieve item scaling

    itemView.setOnTouchListener { view, motionEvent ->
    when (motionEvent.action) {
         MotionEvent.ACTION_DOWN -> {                  
           view.animate().scaleX(1.10f).scaleY(1.10f).setDuration(100).start()
           (itemView.parent as RecyclerView).addOnItemTouchListener(object : 
           RecyclerView.OnItemTouchListener {
             override fun onInterceptTouchEvent(rv: RecyclerView, 
             e: MotionEvent): Boolean {
                   if (rv.scrollState == RecyclerView.SCROLL_STATE_DRAGGING) {
             view.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start() 
             }
             return false               }
             override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
             override fun 
             onRequestDisallowInterceptTouchEvent(disallowIntercept: 
                          Boolean) { }})
             }
         MotionEvent.ACTION_UP -> {                     
               view.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start()
             }
         }
         true
      }
0

Above @ashakirov's answer works fine if you want to scale up and down while pressing(holding) the recylerview item, for those who want this zoom animation for click of an item can do these changes to make that work.

recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/item_animal_height"
    android:background="#f00"
    android:stateListAnimator="@animator/list_animator"/>

res/animator/list_animator.xml (changed android:state_pressed to android:state_selected)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:valueTo="1"/>

            <objectAnimator android:propertyName="scaleY"
                android:valueTo="1"/>
        </set>
    </item>
    <item
        android:state_selected="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:valueTo="0.8"/>

            <objectAnimator android:propertyName="scaleY"
                android:valueTo="0.8"/>
        </set>
    </item>
</selector>

Now maintain a variable for the selected position update it onClick to the position of itemview and call notifyDataSetChanged() as it will trigger OnBindViewHolder where we will change the selected sate of the itemview.

   //add this
        holder.itemView.isSelected = position == selectedPosition
        holder.itemView.setOnClickListener {
            selectedPosition = position
            notifyDataSetChanged()
        }
prem
  • 41
  • 5