本周做了不少需求,这里记录下,此间遇到的知识点。
ViewPager速度的控制
在项目中经常遇到产品这样的需求:要自定义控制ViewPager滑动的速度,而原生ViewPager滑动的速度是无法更改的,因此这里的解决方式是用反射替换ViewPager中的Scroller。
首先自定义一个暴露滑动速度接口的scroller:
public class FixedSpeedScroller extends Scroller {
private int mDuration = 1500;
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
public void setmDuration(int time) {
mDuration = time;
}
public int getmDuration() {
return mDuration;
}
}
然后再ViewPager使用过程中,反射替换即可:
try {
Field mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
FixedSpeedScroller scroller = new FixedSpeedScroller(getContext(),new LinearInterpolator());
mScroller.set(viewPager, scroller);
scroller.setmDuration(200);
} catch (Exception e) {
}
重写equals和hashCode
当我们需要对实体对象进行比较时需要重写equals和hashCode函数。
比较经典的情况是,代码中使用了containsAll、removeAll函数,最终会调用实体类的equals函数。
重写equals函数要遵循自反性、传递性、一致性等原则,一般来说可以如下:
public class Test{
private int a;
private String b;
private float c;
public boolean equals(Object o){
if(o == null){
return false;
}
if(!(o instanceof Test)){
return false;
}
Test t = (Test)o;
return a == t.a && b.equals(t.b) && c == t.c;
}
public int hashCode(){
int result = 17;
result = 37 * result + a;
result = 37 * result + b.hashCode();
result = 37 * result + c;
return result;
}
}
值得注意的是,如果实体内有对象,要递归调用其hashCode函数。
radioButton自定义样式
radioButton根据设置的主题和手机系统的版本不同,可能会呈现各种样式,尤其是其颜色,很可能跟我们的APP不符合,如果想改变其颜色,除了设置主题,只能使用自定义图片替换原生按钮。
首先让UI切好图,然后写好drawable文件,如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true"
android:state_checked="true"
android:drawable="@drawable/select" />
<item
android:state_enabled="true"
android:state_checked="false"
android:drawable="@drawable/normal" />
</selector>
再radioButton里设置设置android:button = “@drawable/radiobutton”,就可以了!
属性动画
今天做了一个图标抖动的需求,效果类似于携程APP主页酒店图标的抖动功能,Demo图如下:
由于GIF比较卡,效果显示不明显,其实图标在摇晃过程中如丝般顺滑,可以手动设置摇晃的次数、时间、角度。
核心代码如下:
private void doShakeAnimation() {
ObjectAnimator animator = buildRotateShakeAnimator(img, 10, 16f, 1980);
img.setTag(animator);
animator.setInterpolator(new LinearInterpolator());
animator.start();
}
/**
*
* @param count 摇晃的次数,一左一右算一次
* @param rotate 摇晃的角度,单位是角度,如:15f就是15度
* @param duration 动画持续的时间
* @return
*/
private ObjectAnimator buildRotateShakeAnimator(ImageView img, int count, float rotate, int duration) {
float xTime = 1f / (count * 2);
int n = 2 * count + 1;
Keyframe[] kf = new Keyframe[n];
float c;//摇摆系数,左摆为负,右为正
for(int i = 0; i < n; i++){
if (i == 0 || i == n - 1) {
c = 0f;
} else if (i % 2 == 0) {
c = 1f;
} else {
c = -1f;
}
kf[i] = Keyframe.ofFloat(i * xTime, c * rotate);
}
PropertyValuesHolder pvhRotate = PropertyValuesHolder.ofKeyframe(View.ROTATION, kf);
return ObjectAnimator.ofPropertyValuesHolder(img, pvhRotate).setDuration(duration);
}
最后一句血的教训:功能做出来不要高兴太早,想想会不会有兼容性问题!