ボタンの最初のクリックで、View
をx軸に沿ってスライドさせます(たとえば200ピクセル右に移動します)。ボタンを2回押すと、View
をx軸に沿って元の位置にスライドさせて戻します。
View.setTranslationX(float)
メソッドjumpsそれぞれmyView.setTranslationX(200);
およびmyView.setTranslationX(0);
を呼び出して、ターゲットの水平位置にビューをジャンプします。代わりにターゲットの水平位置にView
をslideする方法を知っている人はいますか?
注1:
TranslateAnimation
は実際にはView
を移動せず、動いているように見えるだけなので、ダメです。注2:
setTranslationX(float)
およびsetTranslationY(float)
メソッドがAPIレベル11の時点で導入されたという質問を投げかけたとき、私は気づきませんでした。 Honeycomb(API Level 11)を上方にターゲットする場合、Gautam Kの答えで十分です。それ以外の場合は、推奨される解決策についての私の答えを参照してください。
これはかなりの数日間困惑しました(アイスクリームサンドイッチの前にそれを動作させる)が、私はついにそこに着いたと思います! (リードしてくれたGautam KとMike Israelに感謝します)最後にやったのは、必要に応じてView
(a FrameLayout
)を拡張して、右/左アニメーションの翻訳を開始し、聞くことでした次のように、必要に応じてFrameLayout
を右/左に再配置するために、アニメーションの最後に:
_public class SlidingFrameLayout extends FrameLayout
{
private final int durationMilliseconds = 1000;
private final int displacementPixels = 200;
private boolean isInOriginalPosition = true;
private boolean isSliding = false;
public SlidingFrameLayout(Context context)
{
super(context);
}
public SlidingFrameLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SlidingFrameLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onAnimationEnd()
{
super.onAnimationEnd();
if (isInOriginalPosition)
offsetLeftAndRight(displacementPixels);
else
offsetLeftAndRight(-displacementPixels);
isSliding = false;
isInOriginalPosition = !isInOriginalPosition;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
// need this since otherwise this View jumps back to its original position
// ignoring its displacement
// when (re-)doing layout, e.g. when a fragment transaction is committed
if (changed && !isInOriginalPosition)
offsetLeftAndRight(displacementPixels);
}
public void toggleSlide()
{
// check whether frame layout is already sliding
if (isSliding)
return; // ignore request to slide
if (isInOriginalPosition)
startAnimation(new SlideRightAnimation());
else
startAnimation(new SlideLeftAnimation());
isSliding = true;
}
private class SlideRightAnimation extends TranslateAnimation
{
public SlideRightAnimation()
{
super(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, displacementPixels,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0);
setDuration(durationMilliseconds);
setFillAfter(false);
}
}
private class SlideLeftAnimation extends TranslateAnimation
{
public SlideLeftAnimation()
{
super(
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, -displacementPixels,
Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 0);
setDuration(durationMilliseconds);
setFillAfter(false);
}
}
}
_
最後に、SlidingFrameLayout
を左右にスライドするには、SlidingFrameLayout.toggleSlide()
メソッドを呼び出すだけです。もちろん、このSlidingFrameLayout
を微調整して、より多くのピクセルをスライドさせたり、より長くスライドさせたりすることもできますが、これで十分です:)
ObjectAnimator とそのスーパークラスValue Animatorを調べてみてください
このようなObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200);
を実行してから、anim.start();
boolean
値を使用し、オブジェクトアニメーターで200,0
で切り替えてスライドバックします
PS:setDuration
メソッドを使用して、アニメーションの完了に要する時間を設定できます
後方互換性を提供する support library を見てみてください。
@AdilHussainが指摘したように、 nineoldandroids と呼ばれるライブラリがあり、これは古いAndroidでも同じ目的に使用できます。
同様の問題がありました。setFillAfterを呼び出すと、TranslateAnimationは実際にビューを移動します( Androidのバグ )。似たようなことをしなければならなかったので、アニメーションリスナを使用して、すべてを正しい場所に移動させます。残念ながら、アニメーションリスナーにもバグがあります( stackoverflow solution )。 stackoverflow solution のソリューションに従って、独自のレイアウトクラスを作成しました。