Androidでスライドを実現するいくつかの方法


スライドを実現するためのいくつかの方法を一例でまとめます.例の主な機能は、指の移動に伴ってカスタムViewを移動させることです.
レイアウトファイルは次のとおりです.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.scu.lly.dragviewtest.view.DragView
        android:layout_width="100dp"
        android:layout_height="100dp" />
</LinearLayout>

方法1:layout方法
ビューが描画されると、onLayout()メソッドが呼び出されて表示位置が設定されます.したがって、ビューのleft、top、right、bottomの4つのプロパティを変更することで、ビューの座標を制御できます.Viewが指でスライドするように制御するには、onTouchEvent()イベントでスライド制御を行う必要があります.コードは次のとおりです.
public class DragView extends View{

    private int mLastX;
    private int mLastY;

    public DragView(Context context) {
        super(context);
        init();
    }

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init(){
        setBackgroundColor(Color.BLUE);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //  layout     
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                break;
        }
        return true;
    }
}

方法2:offsetLeftAndRight()とoffsetTopAndBottom()
この2つの方法は、実は上のようなlayout設定方式のパッケージ化、簡略化であり、layoutでは左left、右rightの2つの方向にoffsetXを加え、上top、下bottomの2つの方向にoffsetYを加え、4つの方向を簡略化するために、Androidは左右方向の設定の代わりにoffsetLeftAndRight()を提供し、offsetTopAndBottom()で上下方向の設定の代わりにした.
上のコードACTIONを変更するだけですMOVEの部分は、以下の通りです.
<span style="white-space:pre">	</span>case MotionEvent.ACTION_MOVE:
                int offsetX = x - mLastX;
                int offsetY = y - mLastY;
                //  layout     
                //layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                //      
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);
                break;

方法3:LayoutParams
LayoutParamsはViewのレイアウトパラメータを保存しているので、LayoutParamsのレイアウトパラメータを動的に変更することで、Viewの位置を変更する効果を達成することができます.getLayoutParams()メソッドでViewのLayoutParamsを取得します.ここで取得したLayoutParamsは、Viewの親レイアウトのタイプに応じて異なるタイプを設定する必要があります.たとえば、このカスタムViewはLinearLayoutに配置されています.getLayoutParams()で取得したのはLinearLayoutです.LayoutParams.したがって、getLayoutParams()でLayoutParamsを取得する前提は、このViewに親レイアウトが必要であることです.
同様に、上記のコードACTIONを変更するだけです.MOVEの部分は、以下の通りです.
case MotionEvent.ACTION_MOVE:
    int offsetX = x - mLastX;
    int offsetY = y - mLastY;
    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
    lp.leftMargin = getLeft() + offsetX;
    lp.topMargin = getTop() + offsetY;
    setLayoutParams(lp);
    break;

LayoutParamsでViewの位置を変更すると、このViewのMarginプロパティが変更されるのも、親レイアウトが必要な理由であり、親レイアウトがあればmarginプロパティの設定が機能する理由であることがわかります.
LayoutParamsを使用してViewの位置を変更するには、親レイアウトのタイプを考慮したくない場合は、View Groupを使用することもできます.MarginLayoutParamsで設定すると便利です.次のようになります.
case MotionEvent.ACTION_MOVE:
    int offsetX = x - mLastX;
    int offsetY = y - mLastY;
    //LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) getLayoutParams();
    ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();
    lp.leftMargin = getLeft() + offsetX;
    lp.topMargin = getTop() + offsetY;
    setLayoutParams(lp);
    break;

効果は同じです.
方式四:scrollToとscrollBy
scrollTo()とscrollBy()の方法について、私のこの文章「Android Scroller大暴露」で詳しく紹介しています.
scrollTo()メソッドとscrollBy()メソッドを使用するには、scrollTo()メソッドとscrollBy()メソッドを使用して移動するのはViewのcontentであり、つまりViewのコンテンツを移動させ、ViewGroupでscrollTo()メソッドとscrollBy()メソッドを使用すると、移動するのは既存のサブViewであり、Viewで使用すると、移動するのはViewのコンテンツである.たとえば、TextView、contentはそのテキスト、ImageView、contentはそのdrawableオブジェクトです.
したがって、上記の例では、直接このように使用します.
scrollBy(offsetX,offsetY);
ビューは移動していないことがわかりましたが、実際には移動が発生しました.ただ、このとき移動したのはビューの内容で、私たちの例のcontentは何もありません.
したがって、このビューを移動させるには、ビューが存在するビューグループでscrollByまたはscrollToメソッドを使用して移動する必要があります.また,利用者が2つの方法で移動する場合,このときの座標方向が通常とは逆であることに注意し,具体的には『Android Scroller大暴露』で説明している.コードは次のとおりです.
case MotionEvent.ACTION_MOVE:
    //int offsetX = x - mLastX;
    //int offsetY = y - mLastY;
    //  ,        
    int offsetX = mLastX - x;
    int offsetY = mLastY - y;
    // View   ViewGroup    
    ((View)getParent()).scrollBy(offsetX,offsetY);
     break;

方式5:Scroller
Scrollerという補助クラスを通じて、scrollToとscrollByを組み合わせることで、より高度なスライド効果を実現することができます.Scrollerクラスの具体的な紹介についても、この文章では「Android Scroller大暴露」を詳しく説明しています.
ここでは、上記の例と組み合わせて、指をスライドさせて持ち上げると、Viewが自動的に元の位置に戻ります.コードは次のとおりです.
public class DragView extends View{

private int mLastX;
    private int mLastY;
    private Scroller mScroller;

    public DragView(Context context) {
        super(context);
        init(context);
    }

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context){
        setBackgroundColor(Color.BLUE);
        mScroller = new Scroller(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mLastX = x;
                mLastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                //int offsetX = x - mLastX;
                //int offsetY = y - mLastY;
                //  ,        
                int offsetX = mLastX - x;
                int offsetY = mLastY - y;
                // View   ViewGroup    
                ((View)getParent()).scrollBy(offsetX,offsetY);
                break;
            case MotionEvent.ACTION_UP:
                View viewGroup = (View) getParent();
                mScroller.startScroll(viewGroup.getScrollX(),viewGroup.getScrollY(),-viewGroup.getScrollX(),-viewGroup.getScrollY());
                //    invalidate
                invalidate();
                break;
        }
    return true;
}

    @Override
    public void computeScroll() {
        super.computeScroll();
        if(mScroller.computeScrollOffset()){
            ((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
        //  ,      invalidate    
        invalidate();
        }
    }
}

以上の5つの方法がよく使われるスライドビューの方法です.プロパティアニメーションとViewDragHelperを使用する2つの方法がありますが、この2つの方法については、ネット上の資料を参照してください.詳しくは説明しません.
(以上の内容は『Android群英伝』のまとめから)