Android基于reclyview实现列表回弹动画效果
作者:云朵好甜dsf
这篇文章主要为大家详细介绍了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); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。