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