support library last android android-layout android-design-library

library - material design android github



El método onClick no funciona correctamente después de que NestedScrollView se desplazó (5)

Encontré la solución para el mismo problema en este hilo: el elemento dentro de RecyclerView no se puede hacer clic justo después de desplazarse

Puede corregir su código agregando layout_behavior a su AppBarLayout . Puede encontrar el código aquí. Fixed AppBarLayout.Behavior . Solo agregue esta clase a su proyecto y corrija su código:

<android.support.design.widget.AppBarLayout android:layout_width="match_parent" app:layout_behavior="yourPackageName.FixAppBarLayoutBehavior" android:layout_height="wrap_content">

Utilicé NestedScrollView con CoordinatorLayout para habilitar la animación de desplazamiento para la Barra de herramientas (por aplicación: layout_scrollFlags = "scroll | enterAlways").

NestedScrollView contiene LinearLayout como elemento secundario raíz, puse 2 TextViews en LinearLayout para habilitar la animación expandir / contraer. El uno fue establecido Visible y el otro fue establecido en Gone. Y cambiando la visibilidad por el evento onClick de LinearLayout

Normalmente, todo funciona como se esperaba, pero cuando desplacé NestedScrollView, el evento onClick no funciona correctamente. Necesito hacer doble clic después de desplazarme para obtener la animación expandir / contraer

¿Alguien tiene el mismo problema conmigo? por favor, ayúdame

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="98dp" android:paddingLeft="24dp" android:paddingRight="24dp"> <android.support.v7.widget.AppCompatTextView android:id="@+id/detail_expense_reason_trim" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="false" android:textColor="@color/add_new_expense_text_color" /> <android.support.v7.widget.AppCompatTextView android:id="@+id/detail_expense_reason" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="false" android:textColor="@color/add_new_expense_text_color" android:visibility="gone" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.Toolbar android:id="@+id/detail_expense_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </android.support.design.widget.AppBarLayout>

@InjectView(R.id.detail_expense_reason) AppCompatTextView originalReason; @InjectView(R.id.detail_expense_reason_trim) AppCompatTextView trimReason; @InjectView(R.id.detail_expense_container) LinearLayout expenseContainer;

// Manejar evento

public void onClick() { if (originalReason.getVisibility() == View.VISIBLE) { originalReason.setVisibility(View.GONE); trimReason.setVisibility(View.VISIBLE); } else { originalReason.setVisibility(View.VISIBLE); trimReason.setVisibility(View.GONE); } }


Es un error de NestedScrollView, el detalle del error se puede encontrar aquí: issue . El problema es que mScroller.isFinished() en onInterceptTouchEvent(MotionEvent ev) no devolverá true después de una operación de lanzamiento (incluso si se detiene el lanzamiento). Por lo tanto el evento táctil es interceptado.

Este error se ha reportado por un tiempo, pero aún no se ha solucionado. Así que he creado por propia versión de corrección de errores para este problema. Implementé mi propio NestedScrollView , copié todo el código de NestedScrollView y lo NestedScrollView con las siguientes enmiendas:

public class NestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild { ... private void initScrollView() { ... // replace this line: // mScroller = new ScrollerCompat(getContext(), null); mScroller = ScrollerCompat.create(getContext(), null); ... } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { ... switch (action & MotionEventCompat.ACTION_MASK) { ... case MotionEvent.ACTION_DOWN: { ... // replace this line: // mIsBeingDragged = !mScroller.isFinished(); mIsBeingDragged = false; ... } } } }

Y este NestedScrollView debe tener el mismo comportamiento que el original.


Es una mención de Bug en Google #issues 194398 .

Solo necesita usar esta clase de WorkaroundNestedScrollView.java que extiende NestedScrollView como

Solución alternativaNestedScrollView.java

public class WorkaroundNestedScrollView extends NestedScrollView { public WorkaroundNestedScrollView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { // Explicitly call computeScroll() to make the Scroller compute itself computeScroll(); } return super.onInterceptTouchEvent(ev); } }

Y en tu partida, úsalo así.

layout.xml

<com.yourpackagename.whatever.WorkaroundNestedScrollView android:layout_width="match_parent" android:layout_height="match_parent"> ... ... </com.yourpackagename.whatever.WorkaroundNestedScrollView>

Puedes también encontrar más detalles aquí .


He abierto otro problema aquí: https://issuetracker.google.com/issues/68103042 ya que todavía parece ser un problema en Oreo (dispositivos múltiples, incluidos emuladores).

Mi corrección (adaptada de las sugerencias de ta .. @ graymeter.com en https://issuetracker.google.com/issues/37051723 ) no requiere la modificación del código AOSP ya que utiliza la reflexión:

public class MyNestedScrollView extends NestedScrollView { private static final Logger sLogger = LogFactory.getLogger(MyNestedScrollView.class); private OverScroller mScroller; public boolean isFling = false; public MyNestedScrollView(Context context, AttributeSet attrs) { super(context, attrs); mScroller = getOverScroller(); } @Override public void fling(int velocityY) { super.fling(velocityY); // here we effectively extend the super class functionality for backwards compatibility and just call invalidateOnAnimation() if (getChildCount() > 0) { ViewCompat.postInvalidateOnAnimation(this); // Initializing isFling to true to track fling action in onScrollChanged() method isFling = true; } } @Override protected void onScrollChanged(int l, final int t, final int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (isFling) { if (Math.abs(t - oldt) <= 3 || t == 0 || t == (getChildAt(0).getMeasuredHeight() - getMeasuredHeight())) { isFling = false; // This forces the mFinish variable in scroller to true (as explained the // mentioned link above) and does the trick if (mScroller != null) { mScroller.abortAnimation(); } } } } private OverScroller getOverScroller() { Field fs = null; try { fs = this.getClass().getSuperclass().getDeclaredField("mScroller"); fs.setAccessible(true); return (OverScroller) fs.get(this); } catch (Throwable t) { return null; } } }


Yo también encontré este problema

public class NestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild, ScrollingView { @Override public boolean onTouchEvent(MotionEvent ev) { switch (actionMasked) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0) { return false; } //add this line if (!inChild((int) ev.getX(), (int) ev.getY())) { return false; } if ((mIsBeingDragged = !mScroller.isFinished())) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } } } }

y cambio mi archivo xml, cambio paddingTop a margin_top, luego el evento OnClick de mi vista superior flotante no será interceptado por NestedScrollView