Viewflipper 动画在第一次滑动时不起作用
Viewflipper animation doesn't work on first swipe
在我的主 activity 上,我有一个带有三个子视图的取景器。应用程序首次启动后,当我第一次从右向左滑动时,视图发生变化,但没有幻灯片动画。第一次滑动后,向任一方向滑动时动画都按预期工作。我正在关注 this 教程。我使用的代码是:
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
// when user first touches the screen
case MotionEvent.ACTION_DOWN:
{
lastX = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchevent.getX();
// left to right swipe
if (lastX < currentX)
{
if (mViewFlipper.getDisplayedChild() == 0)
break;
mViewFlipper.setInAnimation(this, R.anim.in_from_left);
mViewFlipper.setOutAnimation(this, R.anim.out_to_right);
mViewFlipper.showPrevious();
}
// right to left swipe
if (lastX > currentX)
{
if (mViewFlipper.getDisplayedChild() == mViewFlipper.getChildCount() - 1)
break;
mViewFlipper.setInAnimation(this, R.anim.in_from_right);
mViewFlipper.setOutAnimation(this, R.anim.out_to_left);
mViewFlipper.showNext();
}
break;
}
}
return false;
}
当我调试代码时,我没有发现动画工作和不工作之间有任何区别。此外,我在实际设备和模拟器上看到了这种行为。我错过了什么?如果需要,我可以 post 动画 xml 文件和视图 xml。
编辑:
我能够让它按预期工作的唯一方法是在 onCreate 方法中设置以下内容:
mViewFlipper.setInAnimation(this, R.anim.in_from_right);
mViewFlipper.setOutAnimation(this, R.anim.out_to_left);
mViewFlipper.setFlipInterval(10000);
mViewFlipper.startFlipping();
然后我在第一次滑动时调用 stopFlipping()。对我来说有趣的是,即使没有发生第一次自动翻转,动画也会在第一次滑动时使用这些更改。但是,如果我只是在 onCreate 方法中设置动画而不调用 startFlipping() 方法,它在第一次滑动时仍然没有动画。有人可以解释为什么会出现这种行为吗?
起初,您没有 onTouchEvent
的真正算法。现在你会得到类似动画顺序设置不正确的反转。
尝试使用我的 onTouchEvent
,这对我来说很有魅力:
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
// when user first touches the screen to swap
case MotionEvent.ACTION_DOWN:
{
lastX = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchevent.getX();
// if left to right swipe on screen
if (lastX < currentX)
{
// If no more View/Child to flip
if (viewFlipper.getDisplayedChild() == 0)
break;
// set the required Animation type to ViewFlipper
// The Next screen will come in form Left and current Screen will go OUT from Right
viewFlipper.setInAnimation(this, R.anim.in_from_left);
viewFlipper.setOutAnimation(this, R.anim.out_to_right);
// Show the next Screen
viewFlipper.showNext();
}
// if right to left swipe on screen
if (lastX > currentX)
{
if (viewFlipper.getDisplayedChild() == 1)
break;
// set the required Animation type to ViewFlipper
// The Next screen will come in form Right and current Screen will go OUT from Left
viewFlipper.setInAnimation(this, R.anim.in_from_right);
viewFlipper.setOutAnimation(this, R.anim.out_to_left);
// Show The Previous Screen
viewFlipper.showPrevious();
}
break;
}
}
return true;
}
Try to use this gesture for swipe with animation just get animation swipe left to right and right to left and put inside this:
final GestureDetector gesture = new GestureDetector(getActivity(),
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.i("null", "onFling has been called!");
final int SWIPE_MIN_DISTANCE = 80;
final int SWIPE_MAX_OFF_PATH = 150;
final int SWIPE_THRESHOLD_VELOCITY = 100;
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
try {
//your swipe code
} catch (Exception e) {
n = -1;
}
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
try {
//your swipe code
} catch (Exception e) {
}
}
} catch (Exception e) {
}
return super.onFling(e1, e2, velocityX, velocityY);
}
});
yourFullRelativeLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gesture.onTouchEvent(event);
}
});
yourView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gesture.onTouchEvent(event);
}
});
查看 ViewFlipper class 的源代码,ViewFlipper.showNext() 内部调用 ViewAnimator.showOnly(int position) 方法。
这是在该方法中执行的验证:
void showOnly(int childIndex) {
final boolean animate = (!mFirstTime || mAnimateFirstTime);
showOnly(childIndex, animate);
}
因此,为了实现您想要的效果,您需要告诉 ViewFlipper 为您的 Activity.onCreate:
中的第一个翻转设置动画
@Override
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mViewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);
mViewFlipper.setAnimateFirstView(true);
}
注意:
我能够在不使用 API 级别 22 调用 mViewFlipper.setAnimateFirstView(true) 的情况下实现这一点。但它在以前的版本中似乎并不相同。
在我的主 activity 上,我有一个带有三个子视图的取景器。应用程序首次启动后,当我第一次从右向左滑动时,视图发生变化,但没有幻灯片动画。第一次滑动后,向任一方向滑动时动画都按预期工作。我正在关注 this 教程。我使用的代码是:
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
// when user first touches the screen
case MotionEvent.ACTION_DOWN:
{
lastX = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchevent.getX();
// left to right swipe
if (lastX < currentX)
{
if (mViewFlipper.getDisplayedChild() == 0)
break;
mViewFlipper.setInAnimation(this, R.anim.in_from_left);
mViewFlipper.setOutAnimation(this, R.anim.out_to_right);
mViewFlipper.showPrevious();
}
// right to left swipe
if (lastX > currentX)
{
if (mViewFlipper.getDisplayedChild() == mViewFlipper.getChildCount() - 1)
break;
mViewFlipper.setInAnimation(this, R.anim.in_from_right);
mViewFlipper.setOutAnimation(this, R.anim.out_to_left);
mViewFlipper.showNext();
}
break;
}
}
return false;
}
当我调试代码时,我没有发现动画工作和不工作之间有任何区别。此外,我在实际设备和模拟器上看到了这种行为。我错过了什么?如果需要,我可以 post 动画 xml 文件和视图 xml。
编辑:
我能够让它按预期工作的唯一方法是在 onCreate 方法中设置以下内容:
mViewFlipper.setInAnimation(this, R.anim.in_from_right);
mViewFlipper.setOutAnimation(this, R.anim.out_to_left);
mViewFlipper.setFlipInterval(10000);
mViewFlipper.startFlipping();
然后我在第一次滑动时调用 stopFlipping()。对我来说有趣的是,即使没有发生第一次自动翻转,动画也会在第一次滑动时使用这些更改。但是,如果我只是在 onCreate 方法中设置动画而不调用 startFlipping() 方法,它在第一次滑动时仍然没有动画。有人可以解释为什么会出现这种行为吗?
起初,您没有 onTouchEvent
的真正算法。现在你会得到类似动画顺序设置不正确的反转。
尝试使用我的 onTouchEvent
,这对我来说很有魅力:
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
// when user first touches the screen to swap
case MotionEvent.ACTION_DOWN:
{
lastX = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchevent.getX();
// if left to right swipe on screen
if (lastX < currentX)
{
// If no more View/Child to flip
if (viewFlipper.getDisplayedChild() == 0)
break;
// set the required Animation type to ViewFlipper
// The Next screen will come in form Left and current Screen will go OUT from Right
viewFlipper.setInAnimation(this, R.anim.in_from_left);
viewFlipper.setOutAnimation(this, R.anim.out_to_right);
// Show the next Screen
viewFlipper.showNext();
}
// if right to left swipe on screen
if (lastX > currentX)
{
if (viewFlipper.getDisplayedChild() == 1)
break;
// set the required Animation type to ViewFlipper
// The Next screen will come in form Right and current Screen will go OUT from Left
viewFlipper.setInAnimation(this, R.anim.in_from_right);
viewFlipper.setOutAnimation(this, R.anim.out_to_left);
// Show The Previous Screen
viewFlipper.showPrevious();
}
break;
}
}
return true;
}
Try to use this gesture for swipe with animation just get animation swipe left to right and right to left and put inside this:
final GestureDetector gesture = new GestureDetector(getActivity(),
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.i("null", "onFling has been called!");
final int SWIPE_MIN_DISTANCE = 80;
final int SWIPE_MAX_OFF_PATH = 150;
final int SWIPE_THRESHOLD_VELOCITY = 100;
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
try {
//your swipe code
} catch (Exception e) {
n = -1;
}
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
try {
//your swipe code
} catch (Exception e) {
}
}
} catch (Exception e) {
}
return super.onFling(e1, e2, velocityX, velocityY);
}
});
yourFullRelativeLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gesture.onTouchEvent(event);
}
});
yourView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gesture.onTouchEvent(event);
}
});
查看 ViewFlipper class 的源代码,ViewFlipper.showNext() 内部调用 ViewAnimator.showOnly(int position) 方法。
这是在该方法中执行的验证:
void showOnly(int childIndex) {
final boolean animate = (!mFirstTime || mAnimateFirstTime);
showOnly(childIndex, animate);
}
因此,为了实现您想要的效果,您需要告诉 ViewFlipper 为您的 Activity.onCreate:
中的第一个翻转设置动画 @Override
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
mViewFlipper = (ViewFlipper) findViewById(R.id.viewflipper);
mViewFlipper.setAnimateFirstView(true);
}
注意:
我能够在不使用 API 级别 22 调用 mViewFlipper.setAnimateFirstView(true) 的情况下实现这一点。但它在以前的版本中似乎并不相同。