Heim  >  Artikel  >  Java  >  Angepasste Ansicht in Android, um einen seitlichen Gleiteffekt zu erzielen

Angepasste Ansicht in Android, um einen seitlichen Gleiteffekt zu erzielen

高洛峰
高洛峰Original
2017-01-13 10:34:551142Durchsuche

Rendering:

Angepasste Ansicht in Android, um einen seitlichen Gleiteffekt zu erzielen

Im Internet werden zwei Ansichten zusammengefügt. Standardmäßig wird die rechte Ansicht nicht angezeigt. Allerdings ist der Effekt bei der neuesten Version von QQ nicht so, aber er fühlt sich sehr gut an, daher ist es besser, eine hohe Nachahmung zu verwenden.

Wissenspunkte:

1. Verwendung von ViewDragHelper;
3.

ViewDragHelper gibt es schon seit langem. Wenn Sie es nicht kennen, finden Sie hier einige einfache Methoden, um es zu verwenden >

1. tryCaptureView(View child, int pointerId): Bestimmen Sie, welche untergeordnete Ansicht verschoben werden kann

2. getViewHorizontalDragRange(View child): In meinem schlechten Englisch übersetzt heißt es: „Gibt die Größe der untergeordneten Ansicht zurück, die.“ kann in horizontaler Richtung verschoben werden, in Pixel ist die Einheit Wenn 0 zurückgegeben wird, bedeutet dies, dass es nicht in horizontaler Richtung gezogen werden kann

3. clampViewPositionHorizontal(View child, int left, int dx) : Die Grenze kann hier überprüft werden. Die Position

4 Die Ansicht wird erfasst und die Position ändert sich durch Ziehen oder Festlegen

Seine grundlegende Verwendung ist:


1), erstellen

2) im Konstruktor und Bestimmen Sie, ob in onInterceptTouchEvent
public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
  }
  private void init() {
    viewDragHelper = ViewDragHelper.create(this, callback);
  }
   public boolean onInterceptTouchEvent(MotionEvent ev) {
    boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);
   }
   public boolean onTouchEvent(MotionEvent event) {
    viewDragHelper.processTouchEvent(event);
    return true;
  }

3) abgefangen werden soll, das Ereignis kommt in onTouchEvent heraus

Okay, das am schwierigsten zu verstehende Problem wurde gelöst. Schauen wir uns als nächstes die spezifische Implementierung an:

Schauen wir uns zunächst das Layout an:

Dazu gibt es nichts zu sagen. Eine benutzerdefinierte Ansichtsgruppe enthält zwei Untersteuerelemente.

Dann schauen wir uns an, wie SwipeLayout implementiert wird:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" >
  <scrollviewgroup.lly.com.swiplayout.SwipeLayout
    android:id="@+id/swipeLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
    <!-- delete区域的布局 -->
    <include layout="@layout/layout_delete" />
    <!-- item内容的布局 -->
    <include layout="@layout/layout_content" />
  </scrollviewgroup.lly.com.swiplayout.SwipeLayout>
</LinearLayout>

Der obige Code führt einige Initialisierungsvorgänge aus. Hier erben wir zuerst das Framelayout . Und platzieren Sie es auf der rechten Seite und ändern Sie dann eine ContentView-Ebene darüber, sodass bei der Anzeige nur die ContentView angezeigt wird.

Als nächstes schauen wir uns die Ontouch-Methode an
@Override
  protected void onFinishInflate() {
    super.onFinishInflate();
    deleteView = getChildAt(0);
    contentView = getChildAt(1);
  }
  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    deleteHeight = deleteView.getMeasuredHeight();
    deleteWidth = deleteView.getMeasuredWidth();
    contentWidth = contentView.getMeasuredWidth();
    screenWidth = getWidth();
  }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right,
              int bottom) {
    // super.onLayout(changed, left, top, right, bottom);
    deleteView.layout(screenWidth - deleteWidth, 0, (screenWidth - deleteWidth)
        + deleteWidth, deleteHeight);
    contentView.layout(0, 0, contentWidth, deleteHeight);
  }

Beim Obigen geht es hauptsächlich um die Handhabung von Ereigniskonflikten. Wenn es sich horizontal bewegt, fordert es die übergeordnete Ansicht auf, es nicht abzufangen.

Jetzt kommt der entscheidende Punkt
public boolean onTouchEvent(MotionEvent event) {
    //如果当前有打开的,则下面的逻辑不能执行
    if(!SwipeLayoutManager.getInstance().isShouldSwipe(this)){
      requestDisallowInterceptTouchEvent(true);
      return true;
    }
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        downX = event.getX();
        downY = event.getY();
        break;
      case MotionEvent.ACTION_MOVE:
        //1.获取x和y方向移动的距离
        float moveX = event.getX();
        float moveY = event.getY();
        float delatX = moveX - downX;//x方向移动的距离
        float delatY = moveY - downY;//y方向移动的距离
        if(Math.abs(delatX)>Math.abs(delatY)){
          //表示移动是偏向于水平方向,那么应该SwipeLayout应该处理,请求父view不要拦截
          requestDisallowInterceptTouchEvent(true);
        }
        //更新downX,downY
        downX = moveX;
        downY = moveY;
        break;
      case MotionEvent.ACTION_UP:
        break;
    }
    viewDragHelper.processTouchEvent(event);
    return true;
  }

Wir haben die Methode bereits am Anfang erwähnt. In tryCaptureView machen wir die ContentView verschiebbar , der Schiebebereich ist deleteWidth, die Grenze wird in onViewPositionChanged aktualisiert. Wenn der Finger schließlich angehoben wird, wird die Ansicht automatisch zurückgesetzt Schreiben Sie die Methode „computeScroll“ neu, andernfalls hört der Gleiteffekt auf, sich zu bewegen.

Dieses benutzerdefinierte Framelayout ist jetzt fertig
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
    @Override
    public boolean tryCaptureView(View child, int pointerId) {
      return child==contentView;
    }
    @Override
    public int getViewHorizontalDragRange(View child) {
      return deleteWidth;
    }
    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
      if(child==contentView){
        if(left>0)left = 0;
        if(left<-deleteWidth)left = -deleteWidth;
      }
      return left;
    }
    @Override
    public void onViewPositionChanged(View changedView, int left, int top,
                     int dx, int dy) {
      super.onViewPositionChanged(changedView, left, top, dx, dy);
      //判断开和关闭的逻辑
      if(contentView.getLeft()==0 && currentState!=SwipeState.Close){
        //说明应该将state更改为关闭
        currentState = SwipeState.Close;
        //回调接口关闭的方法
        if(listener!=null){
          listener.onClose(getTag());
        }
        //说明当前的SwipeLayout已经关闭,需要让Manager清空一下
        SwipeLayoutManager.getInstance().clearCurrentLayout();
      }else if (contentView.getLeft()==-deleteWidth && currentState!=SwipeState.Open) {
        //说明应该将state更改为开
        currentState = SwipeState.Open;
        //回调接口打开的方法
        if(listener!=null){
          listener.onOpen(getTag());
        }
        //当前的Swipelayout已经打开,需要让Manager记录一下下
        SwipeLayoutManager.getInstance().setSwipeLayout(SwipeLayout.this);
      }
    }
    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
      super.onViewReleased(releasedChild, xvel, yvel);
      if(contentView.getLeft()<-deleteWidth/2){
        //应该打开
        open();
      }else {
        //应该关闭
        close();
      }
    }
  };

Aber wir haben ein Problem festgestellt, wenn wir in der herausgeschobenen Ansicht nach oben und unten schieben, wird die deleteView dieser Ansicht immer noch angezeigt, also wir Sie müssen es noch zur Aktivität „Verarbeiten“ hinzufügen:

/**
  * 打开的方法
  */
 public void open() {
   viewDragHelper.smoothSlideViewTo(contentView,-deleteWidth,contentView.getTop());
   ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
 }
 /**
  * 关闭的方法
  */
 public void close() {
   viewDragHelper.smoothSlideViewTo(contentView,0,contentView.getTop());
   ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
 };
 public void computeScroll() {
   if(viewDragHelper.continueSettling(true)){
     ViewCompat.postInvalidateOnAnimation(this);
   }
 }

Wenn diese RecyclerView nach oben und unten gleitet, setzen Sie die Unteransicht zurück.

Machen Sie Schluss.

ps: Es wurde ursprünglich in Listview in Eclipse implementiert, aber da Google Eclipse nicht mehr unterstützt und Listview bald durch RecyclerView ersetzt wird, bin ich schließlich auf Android Studio umgestiegen und habe es mit RecyclerView implementiert .

Das Obige ist die benutzerdefinierte Ansicht in Android, die Ihnen der Editor vorstellt, um den seitlichen Gleiteffekt zu erzielen. Wenn Sie Fragen haben, hinterlassen Sie mir und dem Editor bitte eine Nachricht werde Ihnen rechtzeitig antworten. Ich möchte mich auch bei Ihnen allen für Ihre Unterstützung der chinesischen PHP-Website bedanken!
recyView.setOnScrollListener(new RecyclerView.OnScrollListener() {
     @Override
     public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
       super.onScrollStateChanged(recyclerView, newState);
     }
     @Override
     public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
       super.onScrolled(recyclerView, dx, dy);
       if(dy>0 || dy<0){
         SwipeLayoutManager.getInstance().closeCurrentLayout();
       }
     }
   });

Weitere Artikel zum Anpassen von Ansichten in Android, um seitliche Gleiteffekte zu erzielen, finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn