我有一个ViewFlipper
有3个视图,每个视图显示不同的布局,每个孩子都有一个下一个按钮。
单击时,它使用“ViewFlipper”动画转换到另一个孩子。当用户点击动画开始的按钮时,我想要禁用所有按钮以防止动画冲突。 当我在一个按钮上非常快速地点击多次时我面对的是我重新启动动画。
到目前为止我尝试了什么
现在通过将所有animtion对象连接到一个Listener和
保持一个布尔值falg来指示动画是否正在运行。并且在onTouchEvent()
Activity
中如果标志为真我返回true,否则我返回super方法。
此标志在onAnimationStart
回调中设置为true,在onAnimationEnd
中设置为false无效。
当我记录方法调用时,它会显示在动画完全结束之前调用的onAnimationEnd
。
有什么建议可以解决这个问题吗?
代码
public class CreateNewKhtmehActivity extends FragmentActivity implements
OnClickListener, AnimationListener {
AtomicBoolean isAnimationPlaying = new AtomicBoolean(false);
// phase 1
Button phase1_continue_button;
// phase 2
Button phase2_continue_button;
// phase 3
Button phase3_start_session;
/** Called when the activity is first created. */
ViewFlipper flipper;
Animation flip_in_from_left, flip_in_from_right, flip_out_to_left,
flip_out_to_right, stay_still;
RelativeLayout phase1;
RelativeLayout phase2;
RelativeLayout phase3;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.create_new_session);
/*
*
* phase 1
*/
phase1 = (RelativeLayout) findViewById(R.id.phase1);
setUpUIForPhase1(phase1);
// phase2
phase2 = (RelativeLayout) findViewById(R.id.phase2);
setUpUIForPhase2(phase2);
// phase 3
phase3 = (RelativeLayout) findViewById(R.id.phase3);
setUpUIForPhase3(phase3);
/*
* Animation
*/
flipper = (ViewFlipper) findViewById(R.id.main_flipper);
flipper.setDrawingCacheEnabled(true);
flipper.setDisplayedChild(2);
flip_in_from_left = AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.push_in_from_left);
flip_in_from_left.setAnimationListener(this);
flip_in_from_right = AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.push_in_from_right);
flip_in_from_right.setAnimationListener(this);
flip_out_to_left = AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.push_out_to_left);
flip_out_to_left.setAnimationListener(this);
flip_out_to_right = AnimationUtils.loadAnimation(
getApplicationContext(), R.anim.push_out_to_right);
flip_out_to_right.setAnimationListener(this);
stay_still = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.stay_still);
stay_still.setAnimationListener(this);
}
private void setUpUIForPhase3(View v) {
phase3_start_session = (Button) v
.findViewById(R.id.start_session_button);
phase3_start_session.setOnClickListener(this);
}
private void setUpUIForPhase2(View v) {
phase2_continue_button = (Button) v
.findViewById(R.id.phase2_continue_button);
phase2_continue_button.setOnClickListener(this);
}
private void setUpUIForPhase1(View v) {
phase1_continue_button = (Button) phase1
.findViewById(R.id.phase1_continue_Button);
phase1_continue_button.setOnClickListener(this);
}
public void onBackPressed() {
int currentChild = flipper.getDisplayedChild();
switch (currentChild) {
// first displayed child
case 0:
flipNext();
if (this.move_from_phase1_to_phase3) {
flipper.setDisplayedChild(2);
} else {
spinner_from.invalidate();
spinner_to.invalidate();
flipper.setDisplayedChild(1);
}
break;
case 1:
flipNext();
flipper.setDisplayedChild(2);
break;
default:
super.onBackPressed();
}
}
public void onClick(View v) {
System.out.println("onClick");
switch (v.getId()) {
case R.id.phase1_continue_Button:
spinner_from.invalidate();
spinner_to.invalidate();
flipPrevious();
if (this.move_from_phase1_to_phase3) {
flipper.setDisplayedChild(0);
} else {
flipper.setDisplayedChild(1);
}
break;
case R.id.phase2_continue_button:
flipPrevious();
flipper.setDisplayedChild(0);
break;
case R.id.start_session_button:
insetNewSession();
break;
}
}
// Methods concerning the flip
public void flipNext() {
flipper.setInAnimation(flip_in_from_right);
flipper.setOutAnimation(flip_out_to_left);
}
public void flipPrevious() {
flipper.setInAnimation(flip_in_from_left);
flipper.setOutAnimation(flip_out_to_right);
}
public void stayStill() {
flipper.setInAnimation(stay_still);
flipper.setOutAnimation(stay_still);
}
.......
........
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("isAnimationPlaying " + isAnimationPlaying.get());
if (isAnimationPlaying.get()) {
return true;
} else {
return super.onTouchEvent(event);
}
// }
public void onAnimationEnd(Animation animation) {
System.out.println("onAnimationEnd");
isAnimationPlaying.set(true);
}
public void onAnimationRepeat(Animation animation) {
System.out.println("onAnimationRepeat");
}
public void onAnimationStart(Animation animation) {
System.out.println("onAnimationStart");
isAnimationPlaying.set(false);
}
}
答案 0 :(得分:2)
我可以建议2个改进(但我没有机会尝试使用ViewFlipper
,所以我不能保证它会做出所需的技巧):
1)甚至在动画开始之前将标志设置为true
(让它成为按钮点击监听器内部的第一件事)。
2)在尝试延长标志为真的时间时,请勿将其设置为false
内的onAnimationEnd
。而不是直接设置让onAnimationEnd
创建Runnable
(将标志设置为false
)并将其发布以在下一次UI线程准备好时运行。因此,不是立即设置它,而是稍后(一旦运行当前的UI线程工作单元)。万一你不知道 - 内部有一个Runnables的消息队列要在主UI线程上执行。并且onAnimationEnd
作为当前UI更改的一部分在主UI线程上运行。完成UI更改后,您的Runnable
将会被处理。这样您就可以将设置推迟到false。它应该是这样的:
@Override
protected void onAnimationEnd() {
Runnable resetter = new Runnable() {
@Override
public void run() {
yourFlag = false;
}
};
// handler is an instance of android.os.Handler,
// it should be created somewhere before on the main UI thread
// using the simplest Handler() constructor
handler.post(resetter);
}