我需要您对我正在处理的自定义组件的建议。因此,很快,此组件的目的是调整自身大小并在需要时更改视图。所以现在我有一个组件工作:
public class SwitchBox extends FrameLayout {
//Current view being displayed
private View mCurrentView;
//Tell if the custom is currently animating or not
private boolean mAnimating = false;
public SwitchBox(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//When all child are inflated, we set them all to alpha 0...
for(int i = 0; i < getChildCount()-1; i ++) {
getChildAt(i).setAlpha(0f);
getChildAt(i).setVisibility(INVISIBLE);
getChildAt(i).setClickable(false);
}
//Except for the displayed one which called mCurrentView
mCurrentView = getChildAt(getChildCount()-1);
}
@Override
public void bringChildToFront(View child) {
mCurrentView.setClickable(false);
//Animation set for the height and width animation
AnimatorSet anim = new AnimatorSet();
//Setting up width/height animation using nested classes WidthEvaluator and HeightEvaluator
ValueAnimator scaleWidth = ValueAnimator.ofObject(new WidthEvaluator(this), getWidth(), child.getWidth());
scaleWidth.setInterpolator(new AccelerateDecelerateInterpolator());
scaleWidth.setDuration(600);
ValueAnimator scaleHeight = ValueAnimator.ofObject(new HeightEvaluator(this), getHeight(), child.getHeight());
scaleHeight.setInterpolator(new AccelerateDecelerateInterpolator());
scaleHeight.setDuration(600);
//Starting the alpha animation on the current view
//and which end lanching the one on the "new" view
final View view = child;
final View current = mCurrentView;
mCurrentView.animate().alpha(0f).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(VISIBLE);
view.animate().alpha(1f).start();
current.setVisibility(INVISIBLE);
current.animate().setListener(null);
}
@Override
public void onAnimationCancel(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
}).start();
//And then starting the width/height AnimatorSet
anim.play(scaleWidth).with(scaleHeight);
mAnimating = true;
anim.start();
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationEnd(Animator animator) {
view.setClickable(true);
mAnimating = false;
}
@Override
public void onAnimationCancel(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
});
//Finally we change the current view for the new one and bring it to front
mCurrentView = child;
super.bringChildToFront(child);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//To avoid the childs' height and width changing permanently
widthMeasureSpec = MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY);
measureChildren(widthMeasureSpec, heightMeasureSpec);
//While animating we let android do its job
if(!mAnimating) {
//...then when is done we measure the view with the current displayed one
//Mostly (entirely ?) for the initialisation of the component
//but I coud not find another way to tell when all measurement was done
//Yet I tried onLayout/GlobalLayoutListener/... I think overriding onDraw was working well though
setMeasuredDimension(mCurrentView.getMeasuredWidth(), mCurrentView.getMeasuredHeight());
}
}
//Class which allows width animation through ValueAnimator
private class WidthEvaluator extends IntEvaluator {
private View v;
public WidthEvaluator(View v) {
this.v = v;
}
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
Integer num = super.evaluate(fraction, startValue, endValue);
ViewGroup.LayoutParams params = v.getLayoutParams();
params.width = num;
v.requestLayout();
return num;
}
}
//Class which allows height animation through ValueAnimator
private class HeightEvaluator extends IntEvaluator {
private View v;
public HeightEvaluator(View v) {
this.v = v;
}
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
Integer num = super.evaluate(fraction, startValue, endValue);
ViewGroup.LayoutParams params = v.getLayoutParams();
params.height = num;
v.requestLayout();
return num;
}
}
}
只要孩子们设置了特定的大小或WRAP_CONTENT,它就能正常工作。 现在,我想让一个FILL_PARENT的孩子减去一个保证金。我该怎么办? 我想也许想找到一种方法来知道孩子的测量值何时被设置为FILL_PARENT并给他MAX_WIDTH / MAX_HEIGHT维度,但看起来确实正确......
注1: 我可能已经找到了一种更简单的方法来制作动画:
...animate().scaleX(
(float)nextView.getWidth()/(float)currentView.getWidth()
).scaleY(
(float)nextView.getHeight()/(float)currentView.getHeight()
);
但我不确定区别?我的测量问题怎么样,当我调整组件大小时,它会覆盖孩子们的宽度/高度?我做了一些测试,并没有覆盖我只用3个简单的视图作为孩子运行的测量
编辑:规模动画无法发挥作用显然它也会扩大所有孩子,傻我。
注2: 如果你想到任何其他方式来实现我的目标,或者你认为我没有朝着正确的方向前进,请不要犹豫,给我你的意见!
注3: 如果您想要/需要更多代码,我很乐意向您展示迄今为止所有代码。