RecyclerView中带有折叠工具栏的Android字母快速滚动视图
在我的应用程序中,我有这样的activity_main.xml:
<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>
现在我想包括快速滚动到我的recyclerview,使图像date可以在滚动上popup。
这种滚动条的示例图像: –
我search了这一点,并尝试使用几个库,但我认为由于我的折叠工具栏滚动条不能正常工作。
使用滚动库的屏幕截图: –
在我的情况下,滚动条从顶部开始,滚动计算也不合适。
请帮忙解决这个问题。
谢谢
我们想要一些 SectionIndexer
知识 。 这里是SectionIndexer的 Doc 。
我们必须设置TRUE setFastScrollEnabled(true)
方法,它与LISTVIEW
使用…….您可以在下面的示例中使用recyclerview
而不是listView
….
这是活动
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)); } }); } }
这是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>
这是我的自定义适配器与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; } }
这是string.xml文件中的fruits数组。
<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>
最后这是这些代码的输出….
随意问你是否卡在代码之间的任何地方….
注意:FastScroll图片在不同版本的android(例如:棒糖糖,棉花糖等)下会有所不同
对于自定义字母快速的scrollView只需在AppTheme
中的style.xml
文件中添加这两行。
<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
自定义快速Scorll输出: –
这里有一个很好的图书馆。 在Github的这个例子中也有一个很好的教程。
用法:
创build一个RecyclerView.Adapter实现BubbleTextGetter,它给定数据中的位置将返回文本显示在气泡popup。 将FastScroller放置在容器RecyclerView的布局内(可能位于正确的区域)。
自定义FastScroller的一些缺点:
不支持定位更改,但可能很容易修复。 不支持其他布局pipe理器。 只有LinearLayoutManager需要API 11及更高版本。
码:
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>
现在这个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); } } }
这个自定义LinearLayout:
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(); }
您的活动的最后一步创build:
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>