原文链接:https://mp.weixin.qq.com/s/L3o2i3WTmg1ScXEYDS8YCg

在上一篇文章 Android 实现锚点定位中,我们介绍了tablayout+scrollView实现的锚点定位,今天我们使用tablayout+recyclerView 来实现同样的效果。

效果图:

实现思路

实现的思路与上一篇文章是一致的:

1、监听recyclerView滑动到的位置,tablayout切换到对应标签

2、tablayout各标签点击,recyclerView可滑动到对应区域

数据模拟

数据模拟,使用上一文章的AnchorView作为recyclerView的每个字view,同时这里对recyclerView的最后一个子view的高度进行修改,让其充满屏幕。

private LinearLayoutManager manager;
private String[] tabTxt = {"客厅", "卧室", "餐厅", "书房", "阳台", "儿童房"};
//判读是否是recyclerView主动引起的滑动,true- 是,false- 否,由tablayout引起的
private boolean isRecyclerScroll;
//记录上一次位置,防止在同一内容块里滑动 重复定位到tablayout
private 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(this);
int tabH = 50 * 3;
int lastH = screenH - statusBarH - tabH;
manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(new MyAdapter(this, tabTxt, lastH)); @Override
public 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(params);
}
}
}

recyclerView滑动定位

recyclerView滑动引起的,addOnScrollListeneronScrolled的监听第一个可见view的位置,直接将tablayout定位到相应的位置。

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进行切换,recyclerView需要滑动到相应的位置,注意这里需要根据跳转位置不同,进行相应的滑动。

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(position);
} else if (position <= lastItem) {
// 跳转位置在firstItem 之后,lastItem 之间(显示在当前屏幕),smoothScrollBy来滑动到指定位置
int top = mRecyclerView.getChildAt(position - firstItem).getTop();
mRecyclerView.smoothScrollBy(0, top);
} else {
// 如果要跳转的位置在lastItem 之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
// 再通过onScrollStateChanged控制再次调用当前moveToPosition方法,执行上一个判断中的方法
mRecyclerView.smoothScrollToPosition(position);
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);
}
}
});

至此,两种实现锚点定位的方法就介绍到这里,希望能帮助到读者在实际项目中的使用。

代码与上一篇文章的在同一个git地址里。

详细代码见

github地址:https://github.com/taixiang/tabScroll

欢迎关注我的博客:https://blog.manjiexiang.cn/

更多精彩欢迎关注微信号:春风十里不如认识你

有个「佛系码农圈」,欢迎大家加入畅聊,开心就好!



过期了,可加我微信 tx467220125 拉你入群。

Android tabLayout+recyclerView实现锚点定位的更多相关文章

  1. Android 实现锚点定位

    相信做前端的都做过页面锚点定位的功能,通过<a href="#head"> 去设置页面内锚点定位跳转. 本篇文章就使用tablayout.scrollview来实现an ...

  2. [Android]使用RecyclerView替代ListView(三)

    以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4268097.html  这次来使用RecyclerView实现Pinn ...

  3. [Android]使用RecyclerView替代ListView(二)

    以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4242541.html 以前写过一篇“[Android]使用Adapte ...

  4. [Android]使用RecyclerView替代ListView(一)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4232560.html RecyclerView是一个比List ...

  5. html中设置锚点定位的几种常见方法(#号定位)

    在html中设置锚点定位我知道的有几种方法,在此和大家分享一下: 1.使用id定位: <a href="#1F">锚点1</a> <div id=&q ...

  6. [Android]使用RecyclerView替代ListView(四:SeizeRecyclerView)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:<> [Android]使用RecyclerView替代ListView(四:SeizeRecyclerView) 在RecyclerV ...

  7. 【TRICK】解决锚点定位向下浮动Xpx问题

    1. 问题描述 页面滚动后,菜单栏会固定在页头,当锚点定位时,菜单会遮盖部分定位后的内容,所以需要在锚点定位后自动向下漂移Xpx. 2. 解决办法 a. 利用空div 占位,如下: <a hre ...

  8. 当锚点定位遇上position: fixed

    <!DOCTYPE html><html> <head> <title>当锚点定位遇上position: fixed</title> < ...

  9. 锚点定位,jquery定位到页面指定位置

    jquery锚点定位 $('body,html').animate({scrollTop: $('#ter1').offset().top}, 500);#ter1是你要定位的id对象,500是0.5 ...

随机推荐

  1. cpuset

    本文属于内核文档翻译,翻译时没有遵照原文,添加了一些作者的理解,目的不是为了替代内核文档,可以作为阅读内核文档的引子,作者鼓励读者阅读原有的内核文档.原文参考3.10.514内核文档cpuset.tx ...

  2. Linux下安装、启动、停止mongodb

    1.下载完安装包,并解压 tgz(以下演示的是 64 位 Linux上的安装) curl .tgz # 下载 tar .tgz # 解压 mv mongodb/ /usr/local/mongodb ...

  3. vue 关于vue.set的学习笔记

    vue新手小白,在看vue文档的时候 发现vue关于 数组,对象值改变的与 ng有那么点不同. 官方表示 由于 JavaScript 的限制,Vue 不能检测以下变动的数组: 当你利用索引直接设置一个 ...

  4. 在Mac OSX上配置Appium+Android自动化测试环境

    前提准备 开始正文之前,你需要准备好一些基本条件: 1.安装好Mac OSX 操作系统的设备 2.能够访问中国局域网以外资源的方法(没有也行,但很痛苦) 3.已经安装好 homebrew 4.已经安装 ...

  5. FileSync文件同步更新工具

    FileSync是一款文件同步更新工具,它提供了对一个或多个应用的文件进行管理和同步更并功能,基于MD5的文件对比方式可以使管理者轻易地发布需要更新应用文件.FileSync主要模块包括:服务端,CL ...

  6. flask中接收post传递数组方法

    list = request.form.getlist("表单名")

  7. MySQL及其图形界面navicat的安装

    数据库的第一步就是安装MySQL了,基本的安装方法都在这里,所以这里小编整理出来,一方面为了自己复习,一方面也方便大家. (关于MySQL的笔试题,具体见下面博客:http://www.cnblogs ...

  8. SpringBoot(8) SpringBoot过滤器Filter

    1.SpringBoot启动默认加载的Filter characterEncodingFilter hiddenHttpMethodFilter httpPutFormContentFilter re ...

  9. OJ:访问 const 成员函数问题

    Description 补足程序使得其输出结果是: 40 #include <iostream> #include <string> using namespace std; ...

  10. Shuffle过程

    Shuffle过程 在MapReduce框架中,shuffle是连接Map和Reduce之间的桥梁,Map的输出要用到Reduce中必须经过shuffle这个环节,shuffle的性能高低直接影响了整 ...