layout_collapsemode collapsing appbar_scrolling_view_behavior android android-recyclerview material-design android-coordinatorlayout fastscroll

collapsing - Avance rápido de Android alfabético en RecyclerView con la barra de herramientas Colapsar



nestedscrollview (2)

Hay una buena biblioteca here con este example . También hay un buen tutorial here con este ejemplo en Github .

Uso:

crear un RecyclerView.Adapter que implemente BubbleTextGetter, que al darle una posición en los datos devolverá el texto para mostrar en el emergente de burbuja. Coloque el FastScroller dentro del diseño que contiene el RecyclerView (probablemente en el área correcta).

Personalice FastScroller algunas desventajas:

no es compatible con el cambio de orientación, pero probablemente sea fácil de corregir. no es compatible con otros layoutManagers. Solo LinearLayoutManager necesita API 11 y superior.

Código:

BubbleTextGetter

public interface BubbleTextGetter { String getTextToShowInBubble(int pos); }

recycler_view_fast_scroller__fast_scroller.xml

<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="match_parent"> <TextView android:id="@+id/fastscroller_bubble" android:layout_gravity="right|end" android:gravity="center" android:textSize="48sp" tools:text="A" android:layout_width="wrap_content" android:textColor="#FFffffff" android:layout_height="wrap_content" android:background="@drawable/recycler_view_fast_scroller__bubble" android:visibility="visible"/> <ImageView android:id="@+id/fastscroller_handle" android:layout_width="wrap_content" android:layout_marginRight="8dp" android:layout_marginLeft="8dp" android:layout_height="wrap_content" android:src="@drawable/recycler_view_fast_scroller__handle"/> </merge>

Ahora este ScrollListener:

private class ScrollListener extends OnScrollListener { @Override public void onScrolled(RecyclerView rv,int dx,int dy) { View firstVisibleView=recyclerView.getChildAt(0); int firstVisiblePosition=recyclerView.getChildPosition(firstVisibleView); int visibleRange=recyclerView.getChildCount(); int lastVisiblePosition=firstVisiblePosition+visibleRange; int itemCount=recyclerView.getAdapter().getItemCount(); int position; if(firstVisiblePosition==0) position=0; else if(lastVisiblePosition==itemCount-1) position=itemCount-1; else position=firstVisiblePosition; float proportion=(float)position/(float)itemCount; setPosition(height*proportion); } } }

Esta LinearLayout personalizada:

public class FastScroller extends LinearLayout { private static final int BUBBLE_ANIMATION_DURATION=100; private static final int TRACK_SNAP_RANGE=5; private TextView bubble; private View handle; private RecyclerView recyclerView; private final ScrollListener scrollListener=new ScrollListener(); private int height; private ObjectAnimator currentAnimator=null; public FastScroller(final Context context,final AttributeSet attrs,final int defStyleAttr) { super(context,attrs,defStyleAttr); initialise(context); } public FastScroller(final Context context) { super(context); initialise(context); } public FastScroller(final Context context,final AttributeSet attrs) { super(context,attrs); initialise(context); } private void initialise(Context context) { setOrientation(HORIZONTAL); setClipChildren(false); LayoutInflater inflater=LayoutInflater.from(context); inflater.inflate(R.layout.recycler_view_fast_scroller__fast_scroller,this,true); bubble=(TextView)findViewById(R.id.fastscroller_bubble); handle=findViewById(R.id.fastscroller_handle); bubble.setVisibility(INVISIBLE); } @Override protected void onSizeChanged(int w,int h,int oldw,int oldh) { super.onSizeChanged(w,h,oldw,oldh); height=h; } @Override public boolean onTouchEvent(@NonNull MotionEvent event) { final int action=event.getAction(); switch(action) { case MotionEvent.ACTION_DOWN: if(event.getX()<handle.getX()) return false; if(currentAnimator!=null) currentAnimator.cancel(); if(bubble.getVisibility()==INVISIBLE) showBubble(); handle.setSelected(true); case MotionEvent.ACTION_MOVE: setPosition(event.getY()); setRecyclerViewPosition(event.getY()); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: handle.setSelected(false); hideBubble(); return true; } return super.onTouchEvent(event); } public void setRecyclerView(RecyclerView recyclerView) { this.recyclerView=recyclerView; recyclerView.setOnScrollListener(scrollListener); } private void setRecyclerViewPosition(float y) { if(recyclerView!=null) { int itemCount=recyclerView.getAdapter().getItemCount(); float proportion; if(handle.getY()==0) proportion=0f; else if(handle.getY()+handle.getHeight()>=height-TRACK_SNAP_RANGE) proportion=1f; else proportion=y/(float)height; int targetPos=getValueInRange(0,itemCount-1,(int)(proportion*(float)itemCount)); recyclerView.scrollToPosition(targetPos); String bubbleText=((BubbleTextGetter)recyclerView.getAdapter()).getTextToShowInBubble(targetPos); bubble.setText(bubbleText); } } private int getValueInRange(int min,int max,int value) { int minimum=Math.max(min,value); return Math.min(minimum,max); } private void setPosition(float y) { int bubbleHeight=bubble.getHeight(); int handleHeight=handle.getHeight(); handle.setY(getValueInRange(0,height-handleHeight,(int)(y-handleHeight/2))); bubble.setY(getValueInRange(0,height-bubbleHeight-handleHeight/2,(int)(y-bubbleHeight))); } private void showBubble() { AnimatorSet animatorSet=new AnimatorSet(); bubble.setVisibility(VISIBLE); if(currentAnimator!=null) currentAnimator.cancel(); currentAnimator=ObjectAnimator.ofFloat(bubble,"alpha",0f,1f).setDuration(BUBBLE_ANIMATION_DURATION); currentAnimator.start(); } private void hideBubble() { if(currentAnimator!=null) currentAnimator.cancel(); currentAnimator=ObjectAnimator.ofFloat(bubble,"alpha",1f,0f).setDuration(BUBBLE_ANIMATION_DURATION); currentAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); bubble.setVisibility(INVISIBLE); currentAnimator=null; } @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); bubble.setVisibility(INVISIBLE); currentAnimator=null; } }); currentAnimator.start(); }

El último paso en su actividad en onCreate :

setContentView(R.layout.activity_main); RecyclerView recyclerView =(RecyclerView)findViewById(R.id.activity_main_recyclerview); FastScroller fastScroller=(FastScroller)findViewById(R.id.fastscroller); fastScroller.setRecyclerView(recyclerView);

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:ads="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/theme_background" android:id="@+id/drawerlayout"> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:id="@+id/activity_main_id" tools:context="objectdistance.ajai.ram.sita.gallery.MainActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp" android:fitsSystemWindows="true"> <ImageView android:id="@+id/imagetoolbar" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop" android:fitsSystemWindows="true" android:foreground="@drawable/image_header_foreground" app:layout_scrollFlags="scroll" app:layout_collapseMode="parallax"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" android:background="@drawable/theme_background" app:layout_collapseMode="pin" > <Spinner android:id="@+id/spinner_nav" android:layout_width="wrap_content" android:layout_height="wrap_content" android:dropDownVerticalOffset="?attr/actionBarSize" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/activity_main_recyclerview" android:layout_width="match_parent" android:layout_height="@dimen/activity_main_height" android:background="@android:color/darker_gray" /> </android.support.design.widget.CoordinatorLayout> </android.support.v4.widget.DrawerLayout>

En mi aplicación, tengo activity_main.xml así:

<Coordinator Layout> <AppBarLayout> <CollapsingToolbarLayout> <ImageView/> <Toolbar/> </CollapsingToolbarLayout> </AppBarLayout> <RecyclerView/> </Coordinating Layout>

Layout.xml ----- >>>

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:ads="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/theme_background" android:id="@+id/drawerlayout" > <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:id="@+id/activity_main_id" tools:context="objectdistance.ajai.ram.sita.gallery.MainActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp" android:fitsSystemWindows="true"> <ImageView android:id="@+id/imagetoolbar" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop" android:fitsSystemWindows="true" android:foreground="@drawable/image_header_foreground" app:layout_scrollFlags="scroll" app:layout_collapseMode="parallax"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" android:background="@drawable/theme_background" app:layout_collapseMode="pin" > <Spinner android:id="@+id/spinner_nav" android:layout_width="wrap_content" android:layout_height="wrap_content" android:dropDownVerticalOffset="?attr/actionBarSize" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </android.support.design.widget.CoordinatorLayout> <ListView android:layout_width="200dp" android:layout_height="match_parent" android:id="@+id/navlist" android:background="#dedede" android:layout_gravity="start" /> </android.support.v4.widget.DrawerLayout>

Ahora quiero incluir un desplazamiento rápido a mi vista de reciclador para que la fecha de la imagen se pueda desplegar.

Imagen de muestra de dicha barra de desplazamiento: -

Busqué esto e intenté usar algunas bibliotecas, pero creo que debido a la barra de herramientas que se está colapsando, la barra de desplazamiento no funciona correctamente.

Captura de pantalla de la biblioteca de desplazamiento utilizada: -

Aquí en mi caso, la barra de desplazamiento está comenzando desde arriba y el cómputo de desplazamiento tampoco es correcto.

Por favor ayuda a resolver este problema.

Gracias


queremos conocimiento de SectionIndexer . Aquí está el Doc de SectionIndexer .

Tenemos que establecer el setFastScrollEnabled(true) TRUE setFastScrollEnabled(true) , que se usa con LISTVIEW ....... Puede usar recyclerview lugar de listView en el ejemplo siguiente ....

esto es actividad

public class FastScoll extends ListActivity { ListView fruitView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fast_scoll); fruitView = (ListView) findViewById(android.R.id.list); fruitView.setFastScrollEnabled(true); String[] fruits = getResources().getStringArray(R.array.fruits_array); final List<String> fruitList = Arrays.asList(fruits); Collections.sort(fruitList); setListAdapter(new ListAdapter(this, fruitList)); fruitView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View arg1, int position, long arg3) { Log.e("sushildlh",fruitList.get(position)); } }); } }

este es el archivo activity_fast_scoll.xml

<RelativeLayout 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" android:padding="5dp" > <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbarStyle="outsideOverlay" /> </RelativeLayout>

y este es mi adaptador personalizado con SectionIndexer ....

public class ListAdapter extends ArrayAdapter<String> implements SectionIndexer { String[] sections; List<String> fruits; List<String> sectionLetters=new ArrayList<String>(); public ListAdapter(Context context, List<String> fruitList) { super(context, android.R.layout.simple_list_item_1, fruitList); this.fruits = fruitList; for (int x = 0; x < fruits.size(); x++) { String fruit = fruits.get(x); String ch = fruit.charAt(0)+""; ch = ch.toUpperCase(Locale.US); sectionLetters.add(ch); } ArrayList<String> sectionList = new ArrayList<String>(sectionLetters); sections = new String[sectionList.size()]; sectionList.toArray(sections); } public int getPositionForSection(int section) { Log.e("sushildlh", "" + section); return section; } public int getSectionForPosition(int position) { Log.d("sushildlh", "" + position); return position; } public Object[] getSections() { return sections; } }

esto es una matriz de frutas en el archivo string.xml.

<string-array name="fruits_array"> <item>Apples</item> <item>Apricots</item> <item>Avocado</item> <item>Annona</item> <item>Banana</item> <item>Bilberry</item> <item>Blackberry</item> <item>Custard Apple</item> <item>Clementine</item> <item>Cantalope</item> <item>Coconut</item> <item>Currant</item> <item>Cherry</item> <item>Cherimoya</item> <item>Date</item> <item>Damson</item> <item>Durian</item> <item>Elderberry</item> <item>Fig</item> <item>Feijoa</item> <item>Grapefruit</item> <item>Grape</item> <item>Gooseberry</item> <item>Guava</item> <item>Honeydew melon</item> <item>Huckleberry</item> <item>Jackfruit</item> <item>Juniper Berry</item> <item>Jambul</item> <item>Jujube</item> <item>Kiwi</item> <item>Kumquat</item> <item>Lemons</item> <item>Limes</item> <item>Lychee</item> <item>Mango</item> <item>Mandarin</item> <item>Mangostine</item> <item>Nectaraine</item> <item>Orange</item> <item>Olive</item> <item>Prunes</item> <item>Pears</item> <item>Plum</item> <item>Pineapple</item> <item>Peach</item> <item>Papaya</item> <item>Passionfruit</item> <item>Pomegranate</item> <item>Pomelo</item> <item>Raspberries</item> <item>Rock melon</item> <item>Rambutan</item> <item>Strawberries</item> <item>Sweety</item> <item>Salmonberry</item> <item>Satsuma</item> <item>Tangerines</item> <item>Tomato</item> <item>Ugli</item> <item>Watermelon</item> <item>Woodapple</item> </string-array>

y finalmente este es el resultado de este código ...

No dude en preguntar si se ha quedado atrapado en algún lugar entre el código ...

Nota: - La imagen de FastScroll será diferente en diferentes versiones de Android (por ejemplo: -lollipop, marshmallow, etc.) debajo de la salida es para lollipop

Para Personalizar Alphabetical Fast scrollView solo agrega estas 2 líneas en tu archivo AppTheme en AppTheme .

<item name="android:fastScrollTextColor">@color/apptheme_color</item> //this is used for the color of the Alphabetical Fast scrollView <item name="android:fastScrollPreviewBackgroundRight">@drawable/bg_default_focused_holo_light</item> //this is the image or and drawable file you want to set on Alphabetical Fast scrollView

Salida Custom Scorll personalizada: -