一、实现原理
获取GridView原有选择框,替换为一个动画选择框。
将GridView的Selector设置为透明,自定义一个imageView覆盖在GirdView上模拟选择框。
详细代码请查看Github,https://github.com/Ada0mm/viewDemo
二、基于模块
Drawable
ValueAnimator
TypeEvaluator
三、实现步骤
1、布局文件
将GridView本身的selector设置为透明,自定义一个ImageView模拟焦点框,对其实现动画
<GridView android:id="@+id/my_gridview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:cacheColorHint="#00000000" android:fadingEdge="none" android:focusable="true" android:gravity="center" android:horizontalSpacing="19dp" 设置选择框为透明 android:listSelector="@android:color/transparent" android:descendantFocusability="blocksDescendants" android:numColumns="5" android:scrollbars="none" android:stretchMode="columnWidth" android:verticalSpacing="39dp" /> <!-- 自定义焦点框,模拟selector--> <ImageView android:id="@+id/selector" android:layout_width="206dp" android:layout_height="106dp" android:background="@drawable/ada_focus" android:visibility="invisible" />
2、自定义选择框
继承drawable,扩展Animatable接口
定义TypeEvaluator,这里以drawable的起始位置及结束位置为参数区间。
private static class PositionEvaluator implements TypeEvaluator { private IntEvaluator mEvaluator; public PositionEvaluator() { mEvaluator = new IntEvaluator(); } @Override public Object evaluate(float fraction, Object startValue, Object endValue) { Rect startRect = (Rect) startValue; Rect endRect = (Rect) endValue; int left = (Integer) mEvaluator.evaluate(fraction, startRect.left, endRect.left); int top = (Integer) mEvaluator.evaluate(fraction, startRect.top, endRect.top); return new Rect(left, top, left + startRect.width(), top + startRect.height()); } }
定义动画参数
//这里为自定义的imageVie用来显示选择框 //焦点框的ImageView,通过实现这个view的滑动动画,模拟selector的移动。 mView = view; //原有选择框的selector mDrawable = drawable; //定义移动类型为object,根据drawable的原始位置、结束位置以及时长来决定动画 mPositionEvaluator = new PositionEvaluator(); mAnimator = ValueAnimator.ofObject(mPositionEvaluator); mAnimator.setDuration(MOVE_DURATION_MS); mAnimator.setInterpolator(new DecelerateInterpolator(2.0f)); mAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Rect bounds = getBounds(); Rect newBounds = (Rect) animation.getAnimatedValue(); if (!bounds.equals(newBounds)) { AnimatedSelector.super.setBounds(newBounds.left, newBounds.top, newBounds.right, newBounds.bottom); mView.setX(newBounds.left + mLeftOffset); mView.setY(newBounds.top + mTopOffset); }; } });
重写setBounds实现焦点框的移动。
@Override public void setBounds(int left, int top, int right, int bottom) { // Animate setting the bounds. Rect bounds = getBounds(); if (bounds.isEmpty()) { super.setBounds(left, top, right, bottom); mView.setX(left + mLeftOffset); mView.setY(left + mTopOffset); setSelectorDimensions(right - left, bottom - top + 8); ensureViewVisible(); } else if (bounds.left != left || bounds.top != top) { if (mAnimator.isRunning()) { mAnimator.cancel(); mAnimator.setDuration(MOVE_DURATION_MS- ((long) mAnimator. getAnimatedFraction() * MOVE_DURATION_MS)); // System.out.println(">>>>>>"+mAnimator.getDuration()); } else { mAnimator.setDuration(MOVE_DURATION_MS); } mAnimator.setObjectValues(copyBounds(), new Rect(left, top, right, bottom)); mAnimator.setEvaluator(mPositionEvaluator); mAnimator.start(); } }
3. 初始化Gridview,替换为自定义选择框drawable
public void setSelector(GridView gridView) { private AnimatedSelector animatedSelector; animatedSelector = new AnimatedSelector(mContext,selector, gridView.getSelector()); animatedSelector.hideView(); gridView.setSelector(animatedSelector); }
详细代码请查看Github,https://github.com/Ada0mm/viewDemo