Android基于reclyview实现列表回弹动画效果

Android基于reclyview实现列表回弹动画效果

reclyview实现列表回弹动画效果,供大家参考,具体内容如下

1.reclyview列表布局文件

<com.example.demo1.ReboundLayout         android:id="@+id/view"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:background="#000">             <androidx.recyclerview.widget.RecyclerView                 android:id="@+id/rv"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:fadingEdgeLength="30px"                 android:requiresFadingEdge="horizontal"/> </com.example.demo1.ReboundLayout>

2.item布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_marginTop="40px"     android:layout_gravity="center_vertical">     <ImageView         android:id="@+id/card_item_img"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginLeft="20dp"         android:layout_marginRight="20dp"/> </LinearLayout>

3.适配adapter

public class HomeCardAdapter extends RecyclerView.Adapter<HomeCardAdapter.ViewHolder> {     private LayoutInflater mInflater;     private List<Integer> mDatas;     private OnItemClickListener mOnItemClickListener;     private Context mContext;     public HomeCardAdapter(Context context, List<Integer> datats) {         mInflater = LayoutInflater.from(context);         mDatas = datats;         mContext = context;     }     public class ViewHolder extends RecyclerView.ViewHolder {         public ViewHolder(View arg0) {             super(arg0);         }         ImageView mImg;     }     public interface OnItemClickListener{         void  onClick(int position);     }     public  void  setOnItemClickListener(OnItemClickListener onItemClickListener ){         this.mOnItemClickListener =onItemClickListener;     }     @Override     public int getItemCount() {         return mDatas.size();     }     /**      * 创建ViewHolder      */     @Override     public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {         View view = mInflater.inflate(R.layout.card_item,                 viewGroup, false);         ViewHolder viewHolder = new ViewHolder(view);         viewHolder.mImg = (ImageView) view.findViewById(R.id.card_item_img);         return viewHolder;     }     /**      * 设置值      */     @Override     public void onBindViewHolder(final ViewHolder viewHolder, @SuppressLint("RecyclerView")int i) {         viewHolder.mImg.setImageResource(mDatas.get(i));         if( mOnItemClickListener!= null){             viewHolder.itemView.setOnClickListener( new View.OnClickListener() {                 @Override                 public void onClick(View v) {                     mOnItemClickListener.onClick(i);                     //卡片点击动画                     Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.scale_card);                     viewHolder.itemView.startAnimation(animation);                 }             });         }     } }

4.自定义弹性view

public class ReboundLayout extends LinearLayout implements NestedScrollingParent {     private View mHeaderView;     private View mFooterView;     private static final int MAX_WIDTH = 200;     private View mChildView;     // 解决多点触控问题     private boolean isRunAnim;     private boolean isFlag = false;     private int mDrag = 6;//除数越大可以滑动的距离越短     public ReboundLayout(Context context, AttributeSet attrs) {         super(context, attrs);         setOrientation(LinearLayout.HORIZONTAL);         mHeaderView = new View(context);         mHeaderView.setBackgroundColor(0xfff);         mFooterView = new View(context);         mFooterView.setBackgroundColor(0xfff);     }     public boolean isFlag() {         return isFlag;     }     public void setFlag(boolean flag) {         isFlag = flag;     }     @Override     protected void onFinishInflate() {         super.onFinishInflate();         mChildView = getChildAt(0);         LayoutParams layoutParams = new LayoutParams(MAX_WIDTH, LayoutParams.MATCH_PARENT);         addView(mHeaderView, 0, layoutParams);         addView(mFooterView, getChildCount(), layoutParams);         // 左移         scrollBy(MAX_WIDTH, 0);     }     @Override     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {         super.onMeasure(widthMeasureSpec, heightMeasureSpec);         ViewGroup.LayoutParams params = mChildView.getLayoutParams();         params.width = getMeasuredWidth();     }     /**      * 必须要复写 onStartNestedScroll后调用      */     @Override     public void onNestedScrollAccepted(View child, View target, int axes) {     }     /**      * 返回true代表处理本次事件      */     @Override     public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {         if (target instanceof RecyclerView && !isRunAnim) {             return true;         }         return false;     }     /**      * 复位初始位置      */     @Override     public void onStopNestedScroll(View target) {        startAnimation(new ProgressAnimation());     }     /**      * 回弹动画      */     private class ProgressAnimation extends Animation {         // 预留         private float startProgress = 0;         private float endProgress = 1;         private ProgressAnimation() {             isRunAnim = true;         }         @Override         protected void applyTransformation(float interpolatedTime, Transformation t) {             float progress = ((endProgress - startProgress) * interpolatedTime) + startProgress;             scrollBy((int) ((MAX_WIDTH - getScrollX()) * progress), 0);             if (progress == 1) {                 //滑动停止                 isRunAnim = false;                 isFlag = false;             }         }         @Override         public void initialize(int width, int height, int parentWidth, int parentHeight) {             super.initialize(width, height, parentWidth, parentHeight);             setDuration(200);         }     }     @Override     public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int             dyUnconsumed) {     }     @Override     public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {         // 如果在自定义ViewGroup之上还有父View交给我来处理         getParent().requestDisallowInterceptTouchEvent(true);         // dx>0 往左滑动 dx<0往右滑动         boolean hiddenLeft = dx > 0 && getScrollX() < MAX_WIDTH && !ViewCompat                 .canScrollHorizontally(target, -1);         boolean showLeft = dx < 0 && !ViewCompat.canScrollHorizontally(target, -1);         boolean hiddenRight = dx < 0 && getScrollX() > MAX_WIDTH && !ViewCompat                 .canScrollHorizontally(target, 1);         boolean showRight = dx > 0 && !ViewCompat.canScrollHorizontally(target, 1);         if (hiddenLeft || showLeft || hiddenRight || showRight) {             scrollBy(dx / mDrag, 0);             consumed[0] = dx;         }         // 限制错位问题         if (dx > 0 && getScrollX() > MAX_WIDTH && !ViewCompat.canScrollHorizontally(target, -1)) {             scrollTo(MAX_WIDTH, 0);         }         if (dx < 0 && getScrollX() < MAX_WIDTH && !ViewCompat.canScrollHorizontally(target, 1)) {             scrollTo(MAX_WIDTH, 0);         }         isFlag = true;     }     @Override     public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {         return false;     }     @Override     public boolean onNestedPreFling(View target, float velocityX, float velocityY) {         // 当RecyclerView在界面之内交给它自己惯性滑动         if (getScrollX() == MAX_WIDTH) {             return false;         }         return true;     }     @Override     public int getNestedScrollAxes() {         return 0;     }     /**      * 限制滑动 移动x轴不能超出最大范围      */     @Override     public void scrollTo(int x, int y) {         if (x < 0) {             x = 0;         } else if (x > MAX_WIDTH * 2) {             x = MAX_WIDTH * 2;         }         super.scrollTo(x, y);     } }

5.activity调用

public class MainActivity extends AppCompatActivity {     private List<Integer> mDatas;     private RecyclerView mRecyclerView;     private HomeCardAdapter mAdapter;     private ReboundLayout movingView;     private LinearLayout linearLayout;     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         initData();         LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);         linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);         mRecyclerView.setLayoutManager(linearLayoutManager);         //设置适配器         mAdapter = new HomeCardAdapter(this, mDatas);         mRecyclerView.setAdapter(mAdapter);         mAdapter.setOnItemClickListener(new HomeCardAdapter.OnItemClickListener() {             @Override             public void onClick(int position) {                 switch (position){                     case 0:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 1:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 2:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 3:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 4:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 5:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 6:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                     case 7:                         Toast.makeText(MainActivity.this, "第"+position+"个", Toast.LENGTH_SHORT).show();                         break;                 }             }         });         mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {             @Override             public void onScrollStateChanged(@NonNull @NotNull RecyclerView recyclerView, int newState) {                 super.onScrollStateChanged(recyclerView, newState);                 if (newState == RecyclerView.SCROLL_STATE_IDLE && movingView.isFlag()) {                     if (!recyclerView.canScrollHorizontally(1)) {                         //回弹动画                         springAnim(movingView,-100,0,200,6);                     } else if (!recyclerView.canScrollHorizontally(-1)) {                         springAnim(mRecyclerView,100,0,200,6);                     }                 }                 movingView.setFlag(false);             }         });     }     private void initData() {         movingView = findViewById(R.id.view);         linearLayout = findViewById(R.id.home_card_layout);         mRecyclerView = findViewById(R.id.rv);         mDatas = new ArrayList<>(Arrays.asList(R.drawable.home_control,R.drawable.home_navigation,R.drawable.home_media,                 R.drawable.home_hvac,R.drawable.home_energy,R.drawable.home_account,R.drawable.home_iot));     }     /**      *      * @param view  执行动画的view      * @param from  幅度最大值      * @param to    结束值      * @param tension  张力      * @param friction 摩擦力(值越小 弹的次数越多  0为无限循环 参考值 4)      */     private void springAnim(final View view,float from,float to,double tension,double friction){         SpringSystem system = SpringSystem.create();         Spring spring = system.createSpring();         spring.setCurrentValue(from);         spring.setSpringConfig(new SpringConfig(tension, friction));         spring.addListener(new SimpleSpringListener(){             @Override             public void onSpringUpdate(Spring spring) {                 view.setTranslationX((float) spring.getCurrentValue());             }         });         spring.setEndValue(to);     } }

推荐阅读