traduccion reply quick notificaciones desde contestar android android-animation android-6.0-marshmallow android-toolbar android-7.0-nougat

android - reply - Expandir/contraer la animación de la barra de herramientas Lollipop(aplicación Telegram)



contestar whatsapp desde notificaciones android (4)

Estoy tratando de descubrir cómo se realiza la animación de expandir / contraer de la barra de herramientas. Si echa un vistazo a la configuración de la aplicación Telegram, verá que hay una vista de lista y la barra de herramientas. Cuando se desplaza hacia abajo, la barra de herramientas se contrae y cuando se desplaza hacia arriba se expande. También está la animación de la foto de perfil y la FAB. ¿Alguien tiene alguna pista sobre eso? ¿Crees que construyeron todas las animaciones encima? Tal vez me falta algo de las nuevas API o la biblioteca de soporte.

Noté el mismo comportamiento en la aplicación de calendario de Google, cuando abres la ruleta (no creo que sea una ruleta, pero parece): la barra de herramientas se expande y cuando te desplazas hacia arriba, se contrae.

Solo para aclarar: no necesito el método QuickReturn. Sé que probablemente la aplicación Telegram está usando algo similar. El método exacto que necesito es el efecto de la aplicación Google Calendar. He intentado con

android:animateLayoutChanges="true"

y el método de expansión funciona bastante bien. Pero obviamente, si me desplazo hacia arriba en ListView, la barra de herramientas no se contrae.

También he pensado en agregar un GestureListener pero quiero saber si hay API o métodos más simples para lograrlo.

Si no hay ninguno, creo que iré con GestureListener . Esperemos tener un efecto suave de la animación.

¡Gracias!



Esta es mi implementación:

collapsedHeaderHeight y getAnimationProgress se definen en otro lugar, con la función getAnimationProgress puedo obtener el progreso Expandir / Contraer, getAnimationProgress en este valor, hago mi animación y muestro / oculto el encabezado real.

listForumPosts.setOnScrollListener(new AbsListView.OnScrollListener() { /** * @return [0,1], 0 means header expanded, 1 means header collapsed */ private float getAnimationProgress(AbsListView view, int firstVisibleItem) { if (firstVisibleItem > 0) return 1; // should not exceed 1 return Math.min( -view.getChildAt(0).getTop() / (float) (expandedHeaderHeight - collapsedHeaderHeight), 1); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // at render beginning, the view could be empty! if (view.getChildCount() > 0) { float animationProgress = getAnimationProgress(view, firstVisibleItem); imgForumHeaderAvatar.setAlpha(1-animationProgress); if (animationProgress == 1) { layoutForumHeader.setVisibility(View.VISIBLE); } else { layoutForumHeader.setVisibility(View.GONE); } } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // do nothing } }


Utilice la biblioteca de soporte de diseño http://android-developers.blogspot.in/2015/05/android-design-support-library.html

incluir esto en build.gradle

compile ''com.android.support:design:22.2.0'' compile ''com.android.support:appcompat-v7:22.2.+''

para la vista del reciclador incluya esto también

compile ''com.android.support:recyclerview-v7:22.2.0''

<!-- AppBarLayout allows your Toolbar and other views (such as tabs provided by TabLayout) to react to scroll events in a sibling view marked with a ScrollingViewBehavior.--> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true"> <!-- specify tag app:layout_scrollFlags --> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways"/> <!-- specify tag app:layout_scrollFlags --> <android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:scrollbars="horizontal" android:layout_below="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways"/> <!-- app:layout_collapseMode="pin" will help to pin this view at top when scroll --> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:text="Title" android:gravity="center" app:layout_collapseMode="pin" /> </android.support.design.widget.AppBarLayout> <!-- This will be your scrolling view. app:layout_behavior="@string/appbar_scrolling_view_behavior" tag connects this features --> <android.support.v7.widget.RecyclerView android:id="@+id/list" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>

Su actividad debería extender AppCompatActivity

public class YourActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout); //set toolbar Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); } }

El tema de tu aplicación debería ser así

<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.NoActionBar"> </style> </resources>


Editar:

Desde el lanzamiento de la biblioteca de soporte de Android Design, hay una solución más fácil. Verifica la respuesta de joaquin

-

Así es como lo hice, probablemente hay muchas otras soluciones, pero esta funcionó para mí.

  1. En primer lugar, debe usar una Toolbar con un fondo transparente. La Toolbar desplegable y desplegable es realmente falsa y está debajo de la Toolbar transparente. (puede ver en la primera captura de pantalla a continuación, la que tiene los márgenes, que así es como lo hicieron en Telegram).

    Solo conservamos la Toolbar de Toolbar real para NavigationIcon y el elemento de MenuItem desbordamiento.

  2. Todo lo que está en el rectángulo rojo en la segunda captura de pantalla (es decir, la Toolbar falsa y el Toolbar FloatingActionButton ) es en realidad un encabezado que agrega a la configuración ListView (o ScrollView ).

    Por lo tanto, debe crear un diseño para este encabezado en un archivo separado que podría verse así:

    <!-- The headerView layout. Includes the fake Toolbar & the FloatingActionButton --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:id="@+id/header_container" android:layout_width="match_parent" android:layout_height="@dimen/header_height" android:layout_marginBottom="3dp" android:background="@android:color/holo_blue_dark"> <RelativeLayout android:id="@+id/header_infos_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:padding="16dp"> <ImageView android:id="@+id/header_picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="8dp" android:src="@android:drawable/ic_dialog_info" /> <TextView android:id="@+id/header_title" style="@style/TextAppearance.AppCompat.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/header_picture" android:text="Toolbar Title" android:textColor="@android:color/white" /> <TextView android:id="@+id/header_subtitle" style="@style/TextAppearance.AppCompat.Subhead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/header_title" android:layout_toRightOf="@+id/header_picture" android:text="Toolbar Subtitle" android:textColor="@android:color/white" /> </RelativeLayout> </RelativeLayout> <FloatingActionButton android:id="@+id/header_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:layout_margin="10dp" android:src="@drawable/ic_open_in_browser"/> </FrameLayout>

    (Tenga en cuenta que puede usar márgenes negativos / relleno para que el fab se ubique en 2 Views )

  3. Ahora viene la parte interesante. Para animar la expansión de nuestra Toolbar falsa, implementamos ListView onScrollListener .

    // The height of your fully expanded header view (same than in the xml layout) int headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height); // The height of your fully collapsed header view. Actually the Toolbar height (56dp) int minHeaderHeight = getResources().getDimensionPixelSize(R.dimen.action_bar_height); // The left margin of the Toolbar title (according to specs, 72dp) int toolbarTitleLeftMargin = getResources().getDimensionPixelSize(R.dimen.toolbar_left_margin); // Added after edit int minHeaderTranslation; private ListView listView; // Header views private View headerView; private RelativeLayout headerContainer; private TextView headerTitle; private TextView headerSubtitle; private FloatingActionButton headerFab; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.listview_fragment, container, false); listView = rootView.findViewById(R.id.listview); // Init the headerHeight and minHeaderTranslation values headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height); minHeaderTranslation = -headerHeight + getResources().getDimensionPixelOffset(R.dimen.action_bar_height); // Inflate your header view headerView = inflater.inflate(R.layout.header_view, listview, false); // Retrieve the header views headerContainer = (RelativeLayout) headerView.findViewById(R.id.header_container); headerTitle = (TextView) headerView.findViewById(R.id.header_title); headerSubtitle = (TextView) headerView.findViewById(R.id.header_subtitle); headerFab = (TextView) headerView.findViewById(R.id.header_fab);; // Add the headerView to your listView listView.addHeaderView(headerView, null, false); // Set the onScrollListener listView.setOnScrollListener(this); // ... return rootView; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // Do nothing } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { Integer scrollY = getScrollY(view); // This will collapse the header when scrolling, until its height reaches // the toolbar height headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation)); // Scroll ratio (0 <= ratio <= 1). // The ratio value is 0 when the header is completely expanded, // 1 when it is completely collapsed float offset = 1 - Math.max( (float) (-minHeaderTranslation - scrollY) / -minHeaderTranslation, 0f); // Now that we have this ratio, we only have to apply translations, scales, // alpha, etc. to the header views // For instance, this will move the toolbar title & subtitle on the X axis // from its original position when the ListView will be completely scrolled // down, to the Toolbar title position when it will be scrolled up. headerTitle.setTranslationX(toolbarTitleLeftMargin * offset); headerSubtitle.setTranslationX(toolbarTitleLeftMargin * offset); // Or we can make the FAB disappear when the ListView is scrolled headerFab.setAlpha(1 - offset); } // Method that allows us to get the scroll Y position of the ListView public int getScrollY(AbsListView view) { View c = view.getChildAt(0); if (c == null) return 0; int firstVisiblePosition = view.getFirstVisiblePosition(); int top = c.getTop(); int headerHeight = 0; if (firstVisiblePosition >= 1) headerHeight = this.headerHeight; return -top + firstVisiblePosition * c.getHeight() + headerHeight; }

Tenga en cuenta que hay algunas partes de este código que no probé, así que no dude en resaltar los errores. Pero, en general, sé que esta solución funciona, aunque estoy seguro de que se puede mejorar.

EDITAR 2:

Hubo algunos errores en el código anterior (que no probé hasta hoy ...), así que cambié algunas líneas para que funcione:

  1. Introduje otra variable, minHeaderTranslation, que reemplazó a minHeaderHeight;
  2. Cambié el valor de traducción Y aplicado al encabezado Vista desde:

    headerView.setTranslationY(Math.max(-scrollY, minHeaderTranslation));

    a :

    headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation));

    La expresión anterior no funcionaba en absoluto, lo siento por eso ...

  3. El cálculo de la relación también cambió, por lo que ahora evoluciona desde la parte inferior de la barra de herramientas (en lugar de la parte superior de la pantalla) hasta el encabezado expandido completo.