QQ ist ein Chat-Tool, ohne das jeder nicht leben kann. Es ist sowohl praktisch als auch praktisch. Seit QQ auf 6.0 aktualisiert wurde, wurde das Hauptfenster der seitlichen Gleitbewegungen nach links und rechts verkleinert hat das Erscheinungsbild erheblich verbessert, daher habe ich versucht, die verschiedenen Logiken darin zu verstehen, mit relevanten Informationen zu kombinieren und zu recherchieren.
Wir wissen, dass eine der Hauptklassen hier ViewDragHelper ist, also müssen wir zuerst diese ViewDragHelper-Klasse verstehen Offizielles Dokument stellt es vor. Was gibt es?
Erste Vererbung:
java.lang.Object
android.support.v4.widget.ViewDragHelper
Die direkte übergeordnete Klasse ist Object.
Klassenübersicht
ViewDragHelper ist eine Hilfsklasse zum Schreiben benutzerdefinierter ViewGroups. Sie bietet eine Reihe nützlicher Operationen und Statusverfolgung, um einem Benutzer das Ziehen und Neupositionieren von Ansichten innerhalb seiner übergeordneten ViewGroup zu ermöglichen.
Es handelt sich um eine Werkzeugklasse zum Schreiben benutzerdefinierter ViewGroup. Diese Provinz bietet viele nützliche Methoden und Zustände, mit denen Benutzer ihre Flugbahnen und Positionen in die übergeordnete ViewGroup ziehen und zeichnen können.
Verschachtelte Klassen
ViewDragHelper.Callback
Ein Callback wird als Kommunikationskanal mit dem ViewDragHelper zurück zur übergeordneten Ansicht verwendet.
Ein Rückruf wird als Schnittstelle für die Kommunikation zwischen ViewDragHelper und seiner übergeordneten Ansicht verwendet.
Eine öffentliche statische Methode:
Wir können wissen, dass ViewDragHelper wird über die Methode create() erstellt. Dies wird später im Detail vorgestellt.
Lassen Sie uns einen Blick auf einige Methoden werfen, die verwendet werden müssen:
public boolean tryCaptureView(View child, int pointerId) {} public int getViewHorizontalDragRange(View child) {} public int clampViewPositionHorizontal(View child, int left, int dx) {} public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {} public void onViewReleased(View releasedChild, float xvel, float yvel) {}
Die oben genannten Methoden enthalten detaillierte Kommentare im Code. Schauen Sie sie sich einfach hier an. Als nächstes brauchen wir Um die Methode neu zu schreiben
Okay, nachdem ich so viel gesagt habe, beginnen wir mit einer einfachen Methode, die das Ziehen realisieren kann (ich glaube, wenn Ihre beiden Ansichten gezogen werden können, werden Sie irgendwann feststellen, oh , es ist so einfach in nur wenigen Schritten):
Der erste Schritt besteht darin, die Drag-and-Drop-Funktion zu implementieren (implementieren Sie es in 3 einfachen Schritten)
//1、通过静态方法初始化操作 mDragHelper = ViewDragHelper.create(this, mCallback); /** * 2、传递触摸事件 * * @param ev * @return */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { //让自己的控件自行判断是否去拦截 return mDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { try { //自己去处理触摸事件 mDragHelper.processTouchEvent(event); } catch (Exception e) { e.printStackTrace(); } //返回true,这样才能持续接收,要不然我们不会传递而是被拦截了 return true; } ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() { /** * 根据返回结果决定当前child是否可以拖拽 * 尝试捕获的时候调用,如果返回的是主面板,那么负面版是不能被调用的 * @param child 当前被拖拽的view * @param pointerId 区分多点触摸的id * @return 返回true 是都可以拖拽 * 返回child == mLeftContent 左侧可以移动 * 返回child == mMainContent 右侧可以移动 */ @Override public boolean tryCaptureView(View child, int pointerId) { //这里要返回true,要不然不能拖拽 return true; } /** * 根据建议值修正将要移动的位置 此时并没有发生真正的移动(左右) * * @param child 当前拖拽的view * @param left 新的位置的建议值 oldLeft + dx * @param dx 变化量 和变化之前位置的差值 * @return */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { //返回的拖拽的范围,不对拖拽进行真正的限制,仅仅决定了动画执行的速度 return left; } };
Okay, das erste Rendering Es kann herauskommen, das heißt, es kann per Drag & Drop erreicht werden:
Aber wenn Sie die Aufgabe so einreichen, möchten Sie das nicht um zu arbeiten? Okay, okay, kontrollieren wir die Ziehposition, damit er nicht willkürlich ziehen kann. ,
Der zweite Schritt besteht darin, den Drag-Bereich zu steuern
Wir müssen zuerst diese beiden Steuerelemente abrufen und die Eigenschaften dieser beiden Steuerelemente abrufen Wir betreiben. Also haben wir die Methode umgeschrieben:
/** * Finalize inflating a view from XML. This is called as the last phase * of inflation, after all child views have been added. * 当xml填充完的时候去掉用,在这里我们可以找到我们要去操控的那两个布局 * <p>Even if the subclass overrides onFinishInflate, they should always be * sure to call the super method, so that we get called. */ @Override protected void onFinishInflate() { super.onFinishInflate(); /** * 根据索引来找 */ /** * 得到左边的布局 */ mLeftContent = (ViewGroup) getChildAt(0); /** * 得到主main布局 */ mMainContent = (ViewGroup) getChildAt(1); }
Als nächstes müssen wir die Breite und Höhe ermitteln. Wir wissen, dass sie in onMessure() erhalten werden können, aber nach der Überprüfung ist auch die folgende Methode möglich erhalten:
/** * 当尺寸变化的时候去调用 * This is called during layout when the size of this view has changed * @param w * @param h * @param oldw * @param oldh */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); /** * 屏幕的宽度和高度 */ mHeight = getMeasuredHeight(); mWidth = getMeasuredWidth(); /** * 自定义左侧view拖拽出来的距离 */ mRange = (int) (mWidth * 0.7); }
Okay, wir haben die Breite, Höhe und den Widerstandsabstand erhalten, die wir benötigen, also werden wir sie als nächstes begrenzen.
Wir müssen dies nur zur Methode „clampViewPositionHorizontal()“ hinzufügen, um zu verhindern, dass sich das Hauptpanel nach links bewegt, und das linke Panel kann nur an die mRange-Position auf der rechten Seite verschoben werden. (Sie können es hier ausprobieren)
if (child == mMainContent) { left = fixLeft(left); } /** * 修正方法 * 根据范围去修正左侧的view的可见 * * @param left * @return */ private int fixLeft(int left) { if (left < 0) { return 0; } else if (left > mRange) { return mRange; } return left; }
Zu diesem Zeitpunkt ist unser Grundriss herausgekommen, aber es gibt immer noch ein Problem, das heißt, obwohl wir den Gleiteffekt erreicht haben (den auf der rechten Seite). Es ist entschieden, aber wenn wir die LeftView herausschieben, können wir sie immer noch nach rechts schieben. Wir müssen einen Weg finden, sie einzuschränken, das heißt, ich kann die Ansicht von links nur um die rechte Seite schieben Abstand von mRange. Zu diesem Zeitpunkt müssen wir die Methode überprüfen, die den Wert der geänderten Position ermitteln kann, und ihn dann ändern:
/** * 当view位置改变的时候,处理要做的事情,更新状态,伴随动画,重绘界面 * * 此时view已经发生了位置的改变 * * @param changedView 改变的位置view * @param left 新的左边值 * @param top * @param dx 水平变化量 * @param dy */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); int newLeft = left; //如果我们拖拽的是左面板 if (changedView == mLeftContent) { //新的左侧位置是我们的主面板的左侧加上水平变化量 newLeft = mMainContent.getLeft() + dx; } //进行修正(不能超出我们的规定的范围) newLeft = fixLeft(newLeft); if (changedView == mLeftContent) { //当左面板移动之后,在强制放回去 mLeftContent.layout(0, 0, 0 + mWidth, 0 + mHeight); mMainContent.layout(newLeft, 0, newLeft + mWidth, 0 + mHeight); } //兼容低版本 强制重绘 invalidate(); }
Okay, zu diesem Zeitpunkt ist unser allgemeiner Effekt herausgekommen Schauen wir uns das Rendering an. (Die weiße Farbe in der Mitte stellt hier ein Aufnahmeproblem dar und stellt bei persönlichen Tests kein Problem dar)
Zu diesem Zeitpunkt kann natürlich eine grobe Drag-and-Drop-Implementierung durchgeführt werden unten (Sie müssen zuerst einige Steuerelemente hinzufügen, fügen Sie sie einfach selbst zu den beiden LinearLayouts hinzu)
<?xml version="1.0" encoding="utf-8"?> <com.example.qqsliding.DragLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.qqsliding.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/sidebar_bg"> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF"> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#0CB8F6" android:gravity="center_vertical"> <ImageView android:layout_width="30dp" android:layout_height="30dp" android:layout_marginLeft="15dp" android:src="@mipmap/icon_avatar_white"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="Header"/> <ImageView android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentRight="true" android:layout_marginRight="15dp" android:src="@mipmap/icon_search"/> </RelativeLayout> </LinearLayout> </com.example.qqsliding.DragLayout>
Aber diejenigen, die vorsichtig sind, stellen möglicherweise fest, dass es beim Ziehen besonders steif ist. Das liegt daran, dass wir es getan haben Um keine Animation hinzuzufügen, lesen Sie bitte diesen Artikel, um mehr über das seitliche Schiebemenü für Android zu erfahren (2). alle.
Für weitere Android-Geräte, die ViewDragHelper zur Implementierung einer QQ6.0-ähnlichen seitlichen Schiebeschnittstelle (1) verwenden, beachten Sie bitte die PHP-Chinese-Website für verwandte Artikel!