Android View移動の3つの方法をまとめました。


前言
Androidの開発では、ViewはAndroidの開発者の心の病であり、階段を進もうとする一方で、進級を恐れています。AndroidのViewは階段を登る上で最大の障害物です。今回書くViewの移動のようなものが多すぎます。また、Viewのタッチイベントの伝達も含まれています。これらは非常に重要で、直面しなければならない難題です。しかし、いずれにしても、今克服しない困難は将来困難に克服されます。
その前に、まずAndroid座標系の定義規則とViewの位置パラメータを理解します。

Android座標系
Viewの位置と大きさは、left、top、right、bottomの4つのパラメータによって決定され、これらの4つのパラメータはいずれも親Viewのものに対して決定される。

int width = right-left;
 int height = bottom-top;
Activityでレイアウトが完了したら、Viewのいくつかの方法でこれらのパラメータ情報を取得できます。

//left,top,right,bottom    
 int left = getLeft();
 int top = getTop();
 int right = getRight();
 int bottom = getBottom();
また、Android 3.0以降にx,y,translationX,translationYなどのパラメータを加えます。x,y)はViewがView Groupの左上にあるx,yの値を表し、translationX,tranlationYはViewを一つ並進するために用いられています。デフォルトはすべて0で、ビューのsetTranslationX()/setTranslationY()を呼び出した後に変更されます。

//x,y,translationX,translationY     
 int x = getX();
 int y = getY();
 int translationX = getTranslationX();
 int translationY = getTranslationY();
PS:Viewを呼び出すsetTranslationX()setTranslationY()の方法は、Viewの距離を指定することができますが、このプロセスは瞬時に完了します。Viewの動きを滑らかにするために、Viewの属性アニメーションを使用して、transplationXとTranslationYを指定することができます。

ObjectAnimator valueAnimator = ObjectAnimator.ofFloat(textView, "translationX", 200);
 valueAnimator.setDuration(2000);
 valueAnimator.start();
また、View設定setTranslationX()およびsetTranslationY()の後、設定された値が変化していない場合、一度だけ移動します。すなわち、最初に指定された移動距離です。ソースを確認した後、私達は原因を発見しました。設定値の後に設定された値と現在のtranslationX、tranlationYを比較して、不一致の時に移動します。

Viewのいくつかの基本パラメータを理解した後、Viewに関する3つの移動方法を見ます。
一、Androidシステムで提供されるscrollTo()/scrollBy()の方法でViewの移動を実現する。scrollTo()であろうと、scrollBy()であろうと、その移動の本質はすべてView/View Groupの内容である。そしてその移動の過程は瞬間的に完成したので、より良い移動効果を実現するために、彼はSroller類と結合して使用する必要があります。また、上のTranslationとは違って、移動するのはViewそのものです。この点はよく理解してください。scrollTo()およびscrollBy()は、すべてViewにおける方法であり、Scrollerにおける方法ではないが、Viewの平滑化移動を制御することは、Scrlerクラスとは切り離せない。scrollTo() :とは、移動の絶対位置を指し、位置が変化していなければ、マルチコールが機能しない。

scrollTo移動過程の概略図scrollBy() :は、その本質は依然として呼び出されたscrollTo() であり、現在位置の相対距離を指している(毎回、現在位置と設定されている距離を加算して、scrollToを呼び出す()。これによって、何度も呼び出したら、そのたびに一定距離を移動することが分かります。これはscrollTo()との本質的な違いです。

scrollBy移動過程の概略図
PS:上の二つの図については、実はずっと以来、自分では何が絶対的なのかよく分かりませんので、二つの手の図は分かりやすいかもしれません。また、scrollTo()scrollBy()の移動方向の問題です。上にはすでにAndroidの座標系が描かれています。x軸は左→右が正、y軸は上→下が正です。しかし、これはscrollToとscrollByには適用されません。scrollToとscrollByはちょうど反対です。つまり、x軸の左→右が負です。y軸は上から下まで負です。まるでお父さんのようです。
Screler類の分析:Screler類の中の方法を使ってView/View Groupの内容を移動できるのはなぜですか?私たちは分析してみます。
まずは
SrollerクラスのオブジェクトmScrlerを作成します。
そして
Viewを所定の時間に指定された位置に移動させるには、startScroll()の方法を呼び出します。startScroll()Scrollerの種類の中の方法です。また、Scroller類の中にはfiling()の方法もよく使われています。これは主に平滑化された移動を処理し、通常は滑り後の慣性効果を作り出して、Viewの移動がよりリアルになります。次に私達はstartScroll()のソースコードを見ます。

//     /    。  duration   ,    。          ,       。
 public void startScroll(int startX, int startY, int dx, int dy, int duration) { 
 ...
 }
この方法を呼び出した後、一般的には、Viewのinvalidate() を調整します。この方法は、Viewのdraw()方法をトリガすることができます。draw() computeScroll() を呼び出しました。ソースからcomputeScroll() の空き方法を発見しました。これもなぜcomputeScroll()を書き換える方法が必要なのですか?現在の移動動作はcomputeScroll()において行われるためである。

@Override
 public void computeScroll() {
 if (mScroller.computeScrollOffset()) {
  scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
  //    View postInvalidate()/invalidate(),       View        。
  postInvalidate();
 }
 super.computeScroll();
 }
上にはScrller類の中にもう一つのcomputeScrollOffset()方法がありますが、それは何をするものですか?その主な役割はmCurrXとmCurryに変化があるかどうかを判断し、ある場合はtrueに戻り、ない場合はfalseに戻ります。この方法の判断により、Viewを移動するために継続的な呼び出しが必要かどうかを指示することができる。ここでは、scrollTo()を使用して指に従ってViewを移動させる例を示している。

public class CuView extends LinearLayout {

 private float mStartX;
 private float mStartY;
 private Scroller mScroller;
 /**
 *          
 */
 private boolean isFirstFinish;

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

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

 private void init(Context context) {
 mScroller = new Scroller(context);
 }

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

 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public CuView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
 super(context, attrs, defStyleAttr, defStyleRes);
 init(context);
 }


 /**
 *  View        
 * @param event
 * @return
 */
 @Override
 public boolean onTouchEvent(MotionEvent event) {
 int action = event.getAction();
 switch (action) {
  case MotionEvent.ACTION_DOWN:
  /**
   *         ,              ,    View           。
   */
  if (!isFirstFinish) {
   mStartX = event.getRawX();
   mStartY = event.getRawY();
  }
  break;
  case MotionEvent.ACTION_MOVE:
  scrollTo((int) (mStartX - event.getRawX()), (int) (mStartY - event.getRawY()));
  break;
  case MotionEvent.ACTION_UP:
  //       
  isFirstFinish = true;
  break;
 }
 return true;
 }

 /**
 *   startScroll
 */
 public void startScroll() {
 /**
  *   Scroller    ,
  */
 mScroller.startScroll(20, 20, -500, -500, 5000);
 invalidate();
 }

 @Override
 public void computeScroll() {
 if (mScroller.computeScrollOffset()) {
  scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
  invalidate();
 }
 super.computeScroll();
 }
}
二、動画を使ってViewの移動を実現する。
ここにはViewのTween Animation/Frame Animationと、3.0以降に参加するProperty Animationが含まれています。移動するのはViewのイメージです。View自体の位置や大きさは何も変わりません。
三、ViewのLayoutParaamsを設定してViewを移動する

LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();
 layoutParams.leftMargin = 50;
 textView.requestLayout();
締め括りをつける
以上はAndroid Viewの移動の3つの方式の全部の内容を総括しました。本文の内容は皆さんにAndroidを開発する時に役立ちます。もし疑問があれば、メッセージを残して交流してください。