>

recyclerView完结锚点定位,吸附悬停作用实现

- 编辑:正版管家婆马报彩图 -

recyclerView完结锚点定位,吸附悬停作用实现

在前两篇小说中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 达成的滑动定位的功用,作品能够看自身以前小说Android 完成锚点定位Android tabLayout+recyclerView完成锚点定位留神看的话,这种滑动定位的成效,还足以全体滑动,再增加顶上部分tablayout 吸附悬停的职能。

在上一篇小说 Android 达成锚点定位中,我们介绍了tablayout+scrollView落到实处的锚点定位,后天大家利用tablayout+recyclerView 来达成均等的机能。效果图:

落到实处际效果果与利益:

图片 1image

图片 2image

金玉锦绣思路

布局

注‘Android技巧调换群878873098,款待我们走入交流,畅谈!本群有免费读书材料摄像’并且无需付费享用源码剖析录制

注‘Android技术调换群878873098,款待我们加入调换,畅谈!本群有免费学习材质摄像’而且无偿享用源码分析摄像

落到实处的思绪与上一篇小说是一致的:1、监听recyclerView滑动到的职责,tablayout切换成对应标签2、tablayout各标签点击,recyclerView可滑动到相应区域

这里运用的是七个tablayout。贰个用以占位,位于原始地方,scrollview内部,随scrollview滚动;另叁个则是在滑行进度中,不断滑动,滑动到最上端时吸附在荧屏最上部,客商实操的也是以此tablayout。

多少模拟

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:andro xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.tabscroll.CustomScrollView android: android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="200dp" android:background="#ccc" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这里是顶部内容区域" android:textSize="16sp" /> </LinearLayout> <!--占位的tablayout--> <android.support.design.widget.TabLayout android: android:layout_width="match_parent" android:layout_height="50dp" android:background="#ffffff" app:tabIndicatorColor="@color/colorPrimary" app:tabMode="scrollable" app:tabSelectedTextColor="@color/colorPrimary" /> <LinearLayout android: android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp" /> </LinearLayout> <!--实际用户操作的tablayout--> <android.support.design.widget.TabLayout android: android:layout_width="match_parent" android:layout_height="50dp" android:background="#ffffff" android:visibility="invisible" app:tabIndicatorColor="@color/colorPrimary" app:tabMode="scrollable" app:tabSelectedTextColor="@color/colorPrimary" /> </FrameLayout> </com.tabscroll.CustomScrollView></LinearLayout>

数量模拟,使用上一篇章的AnchorView作为recyclerView的每一个字view,同不常间这里对recyclerView的末梢三个子view的高度进行修改,让其充满显示屏。

实现

private LinearLayoutManager manager;private String[] tabTxt = {"客厅", "卧室", "餐厅", "书房", "阳台", "儿童房"};//判读是否是recyclerView主动引起的滑动,true- 是,false- 否,由tablayout引起的private boolean isRecyclerScroll;//记录上一次位置,防止在同一内容块里滑动 重复定位到tablayoutprivate int lastPos;//用于recyclerView滑动到指定的位置private boolean canScroll;private int scrollToPosition;//tablayout设置标签for (int i = 0; i < tabTxt.length; i++) { tabLayout.addTab(tabLayout.newTab().setText(tabTxt[i]));}//计算内容块所在的高度,全屏高度-状态栏高度-tablayout的高度(这里固定高度50dp),用于recyclerView的最后一个item view填充高度int screenH = getScreenHeight();int statusBarH = getStatusBarHeight;int tabH = 50 * 3;int lastH = screenH - statusBarH - tabH;manager = new LinearLayoutManager;recyclerView.setLayoutManager;recyclerView.setAdapter(new MyAdapter(this, tabTxt, lastH));@Overridepublic void onBindViewHolder(MyViewHolder holder, int position) { holder.anchorView.setContentTxt(tabTxt[position]); holder.anchorView.setAnchorTxt(tabTxt[position]); //判断最后一个view if (position == tabTxt.length - 1) { if (holder.anchorView.getHeight() < lastH) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); params.height = lastH; holder.anchorView.setLayoutParams; } }}

滑动定位的法力能够参照从前的篇章,这里最首假若拓宽吸附悬停的机能。

recyclerView滑动定位

多少最早化:

recyclerView滑动引起的,addOnScrollListeneronScrolled的监听第多少个可知view的任务,直接将tablayout定位到对应的地方。

/** * 占位tablayout,用于滑动过程中去确定实际的tablayout的位置 */private TabLayout holderTabLayout;/** * 实际操作的tablayout, */private TabLayout realTabLayout;private CustomScrollView scrollView;private LinearLayout container;private String[] tabTxt = {"客厅", "卧室", "餐厅", "书房", "阳台", "儿童房"};private List<AnchorView> anchorList = new ArrayList<>();//判读是否是scrollview主动引起的滑动,true-是,false-否,由tablayout引起的private boolean isScroll;//记录上一次位置,防止在同一内容块里滑动 重复定位到tablayoutprivate int lastPos = 0;//监听判断最后一个模块的高度,不满一屏时让最后一个模块撑满屏幕private ViewTreeObserver.OnGlobalLayoutListener listener;for (int i = 0; i < tabTxt.length; i++) { AnchorView anchorView = new AnchorView; anchorView.setAnchorTxt(tabTxt[i]); anchorView.setContentTxt(tabTxt[i]); anchorList.add(anchorView); container.addView(anchorView);}for (int i = 0; i < tabTxt.length; i++) { holderTabLayout.addTab(holderTabLayout.newTab().setText(tabTxt[i])); realTabLayout.addTab(realTabLayout.newTab().setText(tabTxt[i]));}
recyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { //当滑动由recyclerView触发时,isRecyclerScroll 置true if (event.getAction() == MotionEvent.ACTION_DOWN) { isRecyclerScroll = true; } return false; }});recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (isRecyclerScroll) { //第一个可见的view的位置,即tablayou需定位的位置 int position = manager.findFirstVisibleItemPosition(); if (lastPos != position) { tabLayout.setScrollPosition(position, 0, true); } lastPos = position; } }});

一最先让实际的tablayout 移动到占位的tablayout 处,覆盖占位的tablayout。

tablayout切换定位

listener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //计算让最后一个view高度撑满屏幕 int screenH = getScreenHeight(); int statusBarH = getStatusBarHeight(AliHomeMoreActivity.this); int tabH = holderTabLayout.getHeight(); int lastH = screenH - statusBarH - tabH - 16 * 3; AnchorView anchorView = anchorList.get(anchorList.size; if (anchorView.getHeight() < lastH) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); params.height = lastH; anchorView.setLayoutParams; } //一开始让实际的tablayout 移动到 占位的tablayout处,覆盖占位的tablayout realTabLayout.setTranslationY(holderTabLayout.getTop; realTabLayout.setVisibility(View.VISIBLE); container.getViewTreeObserver().removeOnGlobalLayoutListener; }};container.getViewTreeObserver().addOnGlobalLayoutListener;private int getScreenHeight() { return getResources().getDisplayMetrics().heightPixels;}public int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources() .getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result;}

点击tablayout进展切换,recyclerView亟待滑动到对应的职分,注意这里要求依附跳转地方分歧,进行相应的滑动。

scrollview滑动

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { //点击标签,使recyclerView滑动,isRecyclerScroll置false int pos = tab.getPosition(); isRecyclerScroll = false; moveToPosition(manager, recyclerView, pos); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { }});public void moveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int position) { // 第一个可见的view的位置 int firstItem = manager.findFirstVisibleItemPosition(); // 最后一个可见的view的位置 int lastItem = manager.findLastVisibleItemPosition(); if (position <= firstItem) { // 如果跳转位置firstItem 之前,就smoothScrollToPosition可以直接跳转, mRecyclerView.smoothScrollToPosition; } else if (position <= lastItem) { // 跳转位置在firstItem 之后,lastItem 之间,smoothScrollBy来滑动到指定位置 int top = mRecyclerView.getChildAt(position - firstItem).getTop(); mRecyclerView.smoothScrollBy; } else { // 如果要跳转的位置在lastItem 之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置 // 再通过onScrollStateChanged控制再次调用当前moveToPosition方法,执行上一个判断中的方法 mRecyclerView.smoothScrollToPosition; scrollToPosition = position; canScroll = true; }}recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (canScroll) { canScroll = false; moveToPosition(manager, recyclerView, scrollToPosition); } }});

根本在滑行进度那不断监听滑动的离开,再移动实际的tablayout ,当在显示器内时,让其一直覆盖在占位的tablayout 上,看上去是跟着scrollview 一同滑动的;当滑出荧屏时,实际的tablayout 不断移动 使其绝对荧屏静止,看上去是吸附在荧屏顶上部分。

由来,三种达成锚点定位的不二诀要就介绍到那边,希望能协助到读者在实际项目中的使用。代码与上一篇小说的在同多少个git地址里。

scrollView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { isScroll = true; } return false; }});//监听scrollview滑动scrollView.setCallbacks(new CustomScrollView.Callbacks() { @Override public void onScrollChanged(int x, int y, int oldx, int oldy) { //根据滑动的距离y 和 holderTabLayout距离父布局顶部的距离对比, //当y < holderTabLayout.getTop()时,holderTabLayout 仍在屏幕内,realTabLayout不断移动holderTabLayout.getTop()距离,覆盖holderTabLayout //当y > holderTabLayout.getTop()时,holderTabLayout 移出,realTabLayout不断移动y,相对的停留在顶部,看上去是静止的 int translation = Math.max(y, holderTabLayout.getTop; realTabLayout.setTranslationY(translation); if  { for (int i = tabTxt.length - 1; i >= 0; i--) { //需要y减去顶部内容区域的高度(具体看项目的高度,这里demo写死的200dp) if (y - 200 * 3 > anchorList.get.getTop { setScrollPos; break; } } } }});private void setScrollPos(int newPos) { if (lastPos != newPos) { realTabLayout.setScrollPosition(newPos, 0, true); } lastPos = newPos;}

详见代码见能够私聊小编哈

tablayout点击切换

注‘Android手艺沟通群878873098,应接大家投入调换,畅谈!本群有无偿学习资料录制’何况无偿享用源码剖析录制

由于实操的是realtablayout ,所以那边只要求一直监听该tablayout。

//实际的tablayout的点击切换realTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { isScroll = false; int pos = tab.getPosition(); int top = anchorList.get.getTop(); //同样这里滑动要加上顶部内容区域的高度 scrollView.smoothScrollTo(0, top + 200 * 3); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { }});

时至昨日,滑动定位+顶端吸附悬停 的效能截至了。做完之后,再看那一个意义,其实和 支付宝-首页 越来越多那二个页面里的滑动作效果果同样。代码与此前小说的在同二个git地址里。

详尽代码见私聊哈

注‘Android本领沟通群878873098,招待大家参加沟通,畅谈!本群有无偿学习质感录像’并且免费享用源码分析录制

本文由编程应用发布,转载请注明来源:recyclerView完结锚点定位,吸附悬停作用实现