Android TabLayout+ScrollView 实现仿html锚点
来源:互联网 发布:mac更新后重启黑屏 编辑:程序博客网 时间:2024/04/30 02:51
概述
在浏览网页的时候,如果网页内容过长,添加网页内部导航会增加用户体验,也就是添加锚点。
这里是用 TabLayout+ScrollView 为页面添加锚点,实现仿html页面导航功能。
先顺一下思路,2点功能:
- 点击TabLayout条目的时候,对应区域滑动到当前展示位置
- 滑动ScrollView,对应的标签变为选中状态,并且移动到中间位置
这里需要考虑一个问题:如果点击TabLayout条目,内容区域ScrollView发生改变,这种状态下ScrollView滑动是不会导致TabLayout条目发生改变的。
知识点
1、TabLayout的选中监听
mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { int position = tab.getPosition(); // 根据点击的位置,使ScrollView 滑动到对应区域 ...... } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });
2、ScrollView 的滑动监听
sv_bodyContainer.setScrollViewListener(new ScrollChangedScrollView.ScrollViewListener() { @Override public void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy) { // 根据滑动到的当前位置,改变TabLayout的选中位置 } @Override public void onScrollStop(boolean isStop) { } });
3、获得ScrollView滑动距离
int scrollY = scrollView.getScrollY();
4、TabLayout 滑动到指定位置
mTabLayout.setScrollPosition(int position, float positionOffset, boolean updateSelectedText);
5、区分好两个操作动作:1. ScrollView 滚动,改变TabLayout ;2. 点击TabLayout 标签,ScrollView 发生滑动。避免当TabLayout 点击条目的时候,因ScrollView 发生滑动,同时又导致TabLayout改变的循环情况。可用一个标记位来标明当前的动作是由TabLayout 点击条目发起还是ScrollView 手动滑动发起。
6、如果ScrollView是在一个内容模块中滑动,要避免重复调用TabLyout的滑动。
代码实现
布局文件 activity_tab_layout.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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:id="@+id/activity_tab_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.skx.tomike.activity.TabLayoutActivity"> <android.support.design.widget.TabLayout android:id="@+id/anchor_tagContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#a930c3a6" app:tabIndicatorColor="@color/skx_323232" app:tabMode="scrollable" app:tabSelectedTextColor="@color/skx_323232" app:tabTextColor="@color/skx_878787" /> <com.skx.tomike.customview.ScrollChangedScrollView android:id="@+id/anchor_bodyContainer" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/anchor_tagContainer"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/iv_image" android:layout_width="match_parent" android:layout_height="240dp" android:scaleType="fitXY" android:src="@drawable/image_07" /> <TextView android:id="@+id/tv_1" android:layout_width="match_parent" android:layout_height="486dp" android:background="@color/skx_33ff4081" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_2" android:layout_width="match_parent" android:layout_height="420dp" android:background="@color/skx_2cb298" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_3" android:layout_width="match_parent" android:layout_height="630dp" android:background="#568463" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_4" android:layout_width="match_parent" android:layout_height="120dp" android:background="@color/skx_2c3e50" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_5" android:layout_width="match_parent" android:layout_height="420dp" android:background="@color/skx_4dbbcf" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_6" android:layout_width="match_parent" android:layout_height="320dp" android:background="@color/skx_007aff" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_7" android:layout_width="match_parent" android:layout_height="503dp" android:background="@color/skx_7f000000" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_8" android:layout_width="match_parent" android:layout_height="272dp" android:background="@color/skx_85f3f3f3" android:gravity="center" android:textSize="36sp" /> <TextView android:id="@+id/tv_9" android:layout_width="match_parent" android:layout_height="338dp" android:background="@color/skx_959ea7" android:gravity="center" android:textSize="36sp" /> </LinearLayout> </com.skx.tomike.customview.ScrollChangedScrollView></RelativeLayout>
Acitivity 代码,注释得也算详细了
public class TabLayoutActivity extends SkxBaseActivity { private TabLayout tab_tagContainer; private ScrollChangedScrollView sv_bodyContainer; private TextView tv_1; private TextView tv_2; private TextView tv_3; private TextView tv_4; private TextView tv_5; private TextView tv_6; private TextView tv_7; private TextView tv_8; private TextView tv_9; // 头部导航标签 private String[] navigationTag = {"图片", "啤酒", "饮料", "矿泉水", "瓜子", "花生", "八宝粥", "泡面", "鸡爪", "火腿肠"}; /** * 是否是ScrollView主动动作 * false:是ScrollView主动动作 * true:是TabLayout 主动动作 */ private boolean tagFlag = false; /** * 用于切换内容模块,相应的改变导航标签,表示当一个所处的位置 */ private int lastTagIndex = 0; /** * 用于在同一个内容模块内滑动,锁定导航标签,防止重复刷新标签 * true: 锁定 * false ; 没有锁定 */ private boolean content2NavigateFlagInnerLock = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initializeView(); refreshView(); installListener(); } @Override public void initializeView() { super.initializeView(); setContentView(R.layout.activity_tab_layout); tab_tagContainer = (TabLayout) findViewById(R.id.anchor_tagContainer); sv_bodyContainer = (ScrollChangedScrollView) findViewById(R.id.anchor_bodyContainer); tv_1 = (TextView) findViewById(R.id.tv_1); tv_2 = (TextView) findViewById(R.id.tv_2); tv_3 = (TextView) findViewById(R.id.tv_3); tv_4 = (TextView) findViewById(R.id.tv_4); tv_5 = (TextView) findViewById(R.id.tv_5); tv_6 = (TextView) findViewById(R.id.tv_6); tv_7 = (TextView) findViewById(R.id.tv_7); tv_8 = (TextView) findViewById(R.id.tv_8); tv_9 = (TextView) findViewById(R.id.tv_9); } @Override public void refreshView() { super.refreshView(); tv_1.setText(navigationTag[1]); tv_2.setText(navigationTag[2]); tv_3.setText(navigationTag[3]); tv_4.setText(navigationTag[4]); tv_5.setText(navigationTag[5]); tv_6.setText(navigationTag[6]); tv_7.setText(navigationTag[7]); tv_8.setText(navigationTag[8]); tv_9.setText(navigationTag[9]); // 添加页内导航标签 for (String item : navigationTag) { tab_tagContainer.addTab(tab_tagContainer.newTab().setText(item)); } } @Override public void installListener() { super.installListener(); sv_bodyContainer.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { //表明当前的动作是由 ScrollView 触发和主导 if (event.getAction() == MotionEvent.ACTION_DOWN) { tagFlag = true; } return false; } }); sv_bodyContainer.setScrollViewListener(new ScrollChangedScrollView.ScrollViewListener() { @Override public void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy) { scrollRefreshNavigationTag(scrollView); } @Override public void onScrollStop(boolean isStop) { } }); tab_tagContainer.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { //表明当前的动作是由 TabLayout 触发和主导 tagFlag = false; // 根据点击的位置,使ScrollView 滑动到对应区域 int position = tab.getPosition(); // 计算点击的导航标签所对应内容区域的高度 int targetY = 0; switch (position) { case 0: break; case 1: targetY = tv_1.getTop(); break; case 2: targetY = tv_2.getTop(); break; case 3: targetY = tv_3.getTop(); break; case 4: targetY = tv_4.getTop(); break; case 5: targetY = tv_5.getTop(); break; case 6: targetY = tv_6.getTop(); break; case 7: targetY = tv_7.getTop(); break; case 8: targetY = tv_8.getTop(); break; case 9: targetY = tv_9.getTop(); break; default: break; } // 移动到对应的内容区域 sv_bodyContainer.smoothScrollTo(0, targetY + 5); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); } /** * 内容区域滑动刷新导航标签 * * @param scrollView 内容模块容器 */ private void scrollRefreshNavigationTag(ScrollView scrollView) { if (scrollView == null) { return; } // 获得ScrollView滑动距离 int scrollY = scrollView.getScrollY(); // 确定ScrollView当前展示的顶部内容属于哪个内容模块 if (scrollY > tv_9.getTop()) { refreshContent2NavigationFlag(9); } else if (scrollY > tv_8.getTop()) { refreshContent2NavigationFlag(8); } else if (scrollY > tv_7.getTop()) { refreshContent2NavigationFlag(7); } else if (scrollY > tv_6.getTop()) { refreshContent2NavigationFlag(6); } else if (scrollY > tv_5.getTop()) { refreshContent2NavigationFlag(5); } else if (scrollY > tv_4.getTop()) { refreshContent2NavigationFlag(4); } else if (scrollY > tv_3.getTop()) { refreshContent2NavigationFlag(3); } else if (scrollY > tv_2.getTop()) { refreshContent2NavigationFlag(2); } else if (scrollY > tv_1.getTop()) { refreshContent2NavigationFlag(1); } else { refreshContent2NavigationFlag(0); } } /** * 刷新标签 * * @param currentTagIndex 当前模块位置 */ private void refreshContent2NavigationFlag(int currentTagIndex) { // 上一个位置与当前位置不一致是,解锁内部锁,是导航可以发生变化 if (lastTagIndex != currentTagIndex) { content2NavigateFlagInnerLock = false; } if (!content2NavigateFlagInnerLock) { // 锁定内部锁 content2NavigateFlagInnerLock = true; // 动作是由ScrollView触发主导的情况下,导航标签才可以滚动选中 if (tagFlag) { tab_tagContainer.setScrollPosition(currentTagIndex, 0, true); } } lastTagIndex = currentTagIndex; }}
1 1
- Android TabLayout+ScrollView 实现仿html锚点
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android上实现仿IOS弹性ScrollView
- Android 之实现仿IOS弹性ScrollView
- Android TabLayout使用注意点。
- Android仿IOS有弹性ScrollView
- 【Android】Android开发实现带有反弹效果,仿IOS反弹scrollview详解教程
- Android 仿蘑菇街列表弹出和瀑布流 (ScrollView+RelativeLayout实现)
- Android自定义ScrollView实现仿拉手团购详情页标题
- android之自定义viewGroup仿scrollView的两种实现(滚动跟粘性)
- Android仿IOS回弹效果 ScrollView回弹
- android仿IOS,滑动隐藏底部ScrollView
- 语句之概览
- hdu5136Yue Fei's Battle(计数dp)
- javascript arguments(callee、caller)
- 儿童安全座椅
- ecshop数据库表5(ecs_admin_message)管理留言表
- Android TabLayout+ScrollView 实现仿html锚点
- 51NOD1287 加农炮(线段树)
- 手机和电脑如何制作gif动画
- Add your tool into LLVM project - I mean source code.
- linux系统编程之进程(一):进程基本概述
- Android 必备绝杀技
- Python三部曲之1,研究python3的输入输出
- Android SDK Manager 更新代理配置
- jdbc工具类的抽取。