摘要:这里是顶部内容区域占位的实际用户操作的实现滑动定位的功能可以参考之前的文章,这里主要是进行吸附悬停的效果。实际的的点击切换同样这里滑动要加上顶部内容区域的高度这里写死的高度至此,滑动定位顶部吸附悬停的效果结束了。
在前两篇文章中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 实现的滑动定位的功能,文章链接:
Android 实现锚点定位
Android tabLayout+recyclerView实现锚点定位
仔细看的话,这种滑动定位的功能,还可以整体滑动,再加上顶部tablayout 吸附悬停的效果。
实现效果:
布局这里采用的是两个 tablayout。
一个用于占位,位于原始位置,scrollview内部,随scrollview滚动;另一个则是在滑动过程中,不断滑动,滑动到顶部时吸附在屏幕顶部,用户实际操作的也是这个tablayout。
实现
滑动定位的功能可以参考之前的文章,这里主要是进行吸附悬停的效果。
数据初始化:
/** * 占位tablayout,用于滑动过程中去确定实际的tablayout的位置 */ private TabLayout holderTabLayout; /** * 实际操作的tablayout, */ private TabLayout realTabLayout; private CustomScrollView scrollView; private LinearLayout container; private String[] tabTxt = {"客厅", "卧室", "餐厅", "书房", "阳台", "儿童房"}; private ListanchorList = new ArrayList<>(); //判读是否是scrollview主动引起的滑动,true-是,false-否,由tablayout引起的 private boolean isScroll; //记录上一次位置,防止在同一内容块里滑动 重复定位到tablayout private int lastPos = 0; //监听判断最后一个模块的高度,不满一屏时让最后一个模块撑满屏幕 private ViewTreeObserver.OnGlobalLayoutListener listener; for (int i = 0; i < tabTxt.length; i++) { AnchorView anchorView = new AnchorView(this); 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])); }
一开始让实际的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() - 1); if (anchorView.getHeight() < lastH) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); params.height = lastH; anchorView.setLayoutParams(params); } //一开始让实际的tablayout 移动到 占位的tablayout处,覆盖占位的tablayout realTabLayout.setTranslationY(holderTabLayout.getTop()); realTabLayout.setVisibility(View.VISIBLE); container.getViewTreeObserver().removeOnGlobalLayoutListener(listener); } }; container.getViewTreeObserver().addOnGlobalLayoutListener(listener); 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; }scrollview滑动
主要在滑动过程这不断监听滑动的距离,再移动实际的tablayout ,当在屏幕内时,让其一直覆盖在占位的tablayout 上,看上去是跟着scrollview 一起滑动的;当滑出屏幕时,实际的tablayout 不断移动 使其相对屏幕静止,看上去是吸附在屏幕顶部。
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 (isScroll) { for (int i = tabTxt.length - 1; i >= 0; i--) { //需要y减去顶部内容区域的高度(具体看项目的高度,这里demo写死的200dp) if (y - 200 * 3 > anchorList.get(i).getTop() - 10) { setScrollPos(i); break; } } } } }); private void setScrollPos(int newPos) { if (lastPos != newPos) { realTabLayout.setScrollPosition(newPos, 0, true); } lastPos = newPos; }tablayout点击切换
由于实际操作的是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(pos).getTop(); //同样这里滑动要加上顶部内容区域的高度(这里写死的高度) scrollView.smoothScrollTo(0, top + 200 * 3); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } });
至此,滑动定位+顶部吸附悬停 的效果结束了。做完之后,再看这个效果,其实和 支付宝-首页 更多 那个页面里的滑动效果一样。
代码与之前文章的在同一个git地址里。
详细代码见
github地址:https://github.com/taixiang/tabScroll
欢迎关注我的博客:https://blog.manjiexiang.cn/
更多精彩欢迎关注微信号:春风十里不如认识你
有个「佛系码农圈」,欢迎大家加入畅聊,开心就好!
过期了,可加我微信 tx467220125 拉你入群。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/14353.html
摘要:当子设置响应动作为时当向下滑动的时候,子设置了的子下滑至折叠的高度,当到达滑动范围的结束值的时候,滑动剩下的部分开始滑动。这个折叠的高度是通过子的最小高度指定的。以像素为单位设置底部展开的标题边距。 前几天看到这样一个UI效果,然后自己也仿照实现了下: showImg(https://segmentfault.com/img/remote/1460000016555141); 看着挺酷...
摘要:上列表左右滑动开源组件掘金是一款用于为上的排布提供左滑右滑操作的库。这里我贴出最终的兼容方案教你用两层嵌套实现三级展示界面掘金最近项目中使用一个三级展示列表,要求第一级和第二季都可以折叠,并有不同的图标变换,第三层展示数据,可点击。 八年 Android 开发,看我如何简化 Android 的 UI 开发! - Android - 掘金作者 : Super Mary 校对者: Zhao...
摘要:本文就向大家介绍今年最新的深受开发者喜爱的个库。目前提供的功能有和三个位置的吸附指定要分屏的数量,支持水平和垂直分屏,滚动时的回调。只能包含一个子布局,例如,,,等。项目的简介写得很好,易于理解。 Android开发技术越来越成熟,Android开发工具当然也层出叠现。本文就向大家介绍今年最新的深受开发者喜爱的30个Android库。希望对你的Android开发工作能起到助力。 1.M...
摘要:像微信一样的图片选择器像微信一样的图片选择器像微信一样录制视频和音频重构史上最牛逼的音乐播放器仿网易云音乐已开源无论是下载模块,还是换肤模块,还是炫丽的界面通讯录顶部固定的索引效果通讯录和城市列表展示时通用的滑动顶部固定的索引列表效果 Android 仿京东、天猫 app 的商品详情页的布局架构, 以及功能实现 仿京东、天猫 app 的商品详情页 自定义 viewgroup+viewd...
摘要:启动页旅行云阅一个仿网易云音乐,使用及豆瓣开发的开源项目掘金一款基于网易云音乐,使用及豆瓣开发的符合阅读类的开源项目。 Android 仿今日头条的开源项目 - Android - 掘金起因 看到众多大神纷纷有了自己的开源项目,于是自己琢磨着也想做一个开源项目来学习下,因为每次无聊必刷的app就是今日头条,评论简直比内容都精彩,所以我打算仿今日头条来练练手,期间也曾放弃过,也遇到很多坑...
阅读 660·2021-11-25 09:43
阅读 2840·2021-11-23 09:51
阅读 3466·2021-11-19 09:40
阅读 702·2021-09-29 09:34
阅读 1648·2021-09-26 10:21
阅读 684·2021-09-22 15:24
阅读 3926·2021-09-22 15:08
阅读 2938·2021-09-07 09:59