一、实现原理
获取GridView原有选择框,替换为一个动画选择框。
将GridView的Selector设置为透明,自定义一个imageView覆盖在GirdView上模拟选择框。
详细代码请查看Github,https://github.com/Ada0mm/viewDemo
二、基于模块
Drawable
ValueAnimator
TypeEvaluator
三、实现步骤
1、布局文件
将GridView本身的selector设置为透明,自定义一个ImageView模拟焦点框,对其实现动画
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"
/>
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