android实现3种定位的切换,Android 滑动定位+吸附悬停效果实现

在前两篇文章中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 实现的滑动定位的功能,文章链接:

Android 实现锚点定位

Android tabLayout+recyclerView实现锚点定位

仔细看的话,这种滑动定位的功能,还可以整体滑动,再加上顶部tablayout 吸附悬停的效果。

实现效果:

AAffA0nNPuCLAAAAAElFTkSuQmCC

布局

这里采用的是两个 tablayout。

一个用于占位,位于原始位置,scrollview内部,随scrollview滚动;另一个则是在滑动过程中,不断滑动,滑动到顶部时吸附在屏幕顶部,用户实际操作的也是这个tablayout。

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/scrollView"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="200dp"

android:background="#ccc"

android:gravity="center">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="这里是顶部内容区域"

android:textSize="16sp" />

android:id="@+id/tablayout_holder"

android:layout_width="match_parent"

android:layout_height="50dp"

android:background="#ffffff"

app:tabIndicatorColor="@color/colorPrimary"

app:tabMode="scrollable"

app:tabSelectedTextColor="@color/colorPrimary" />

android:id="@+id/container"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical"

android:padding="16dp" />

android:id="@+id/tablayout_real"

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" />

实现

滑动定位的功能可以参考之前的文章,这里主要是进行吸附悬停的效果。

数据初始化:

/**

* 占位tablayout,用于滑动过程中去确定实际的tablayout的位置

*/

private TabLayout holderTabLayout;

/**

* 实际操作的tablayout,

*/

private TabLayout realTabLayout;

private CustomScrollView scrollView;

private LinearLayout container;

private String[] tabTxt = {"客厅", "卧室", "餐厅", "书房", "阳台", "儿童房"};

private List anchorList = 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地址里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/427679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用JavaScript语言判断一个三位数是否为水仙花数

// 提示用户输入一个三位数// 如果不是三位数或者不是数字&#xff0c;则提示“非法输入”&#xff1b;// 如果输入合法&#xff0c;判断这个三位数是否为水仙花数。// &#xff08;每一位数的三次方之和等于这个数本身&#xff0c;就是水仙花数。例如&#xff1a;153 370 371 …

unity mmd不支持android,MMD模型导入Unity的解决方案

前言学了Unity后&#xff0c;总是感觉缺少资源&#xff0c;包括人物、物品模型、动作数据、贴图、特效&#xff0c;各种插件&#xff0c;还被骗去学了几天各种美术软件。说起模型和动作数据&#xff0c;就又想到MMD&#xff0c;毕竟有那么现成的资源&#xff0c;虽然不能商用&a…

关于windows cmd的一些便捷应用

在同事的指点下&#xff0c;我学会了一种非常方便的进入路径的方法 在windows文件夹中直接打开到要执行的文件的位置&#xff0c;然后在我的电脑那个路径当中输入cmd 之后&#xff0c;cmd的对话框会弹出来&#xff0c;并且显示在当前路径下&#xff0c;这样&#xff0c;有一些需…

android中的 listview,Android中ListView的初步认识(一)

ListView是安卓开发中常用的组件之一&#xff0c;它的作用是在一个垂直的列表中展现出所需的项目。接下来&#xff0c;我们看一下ListView的实现方法&#xff1a;第一种 是常见的在XML中定义然后在activity中使用findViewById来获取的方式(这个相当基础了&#xff0c;直接代码)…

Tcl 语言改写Java题目-1

Java题目:https://blog.csdn.net/wenzhi20102321/article/details/52274976 Program1. proc fun_1 {x} { if {$x<3} { return 1 } else { return [expr [fun_1 [expr $x - 1]] [fun_1 [expr $x - 2]]] }}puts [fun_1 10] program 2 #判断是不是素数…

android开发app初始化,安卓快速开发框架(一)XBaseAndroid初始化使用

XBaseAndroid如果您需要使用最新版可以去github查看。该文章描述的是1.0.9.4版本。使用AndroidStudio 3.0创建一个新的安卓项目如果您不知道如何创建&#xff0c;请猛戳此处。配置仓库引用项目结构.png点击build.gradle(Project)&#xff0c;添加以下maven仓库。allprojects {r…

Python之模块与包(下)

1、什么是包 #官网解释 Packages are a way of structuring Python’s module namespace by using “dotted module names” 包是一种通过使用‘.模块名’来组织python模块名称空间的方式。 #具体的&#xff1a;包就是一个包含有__init__.py文件的文件夹&#xff0c;所以其实我…

html 状态 304,网站频繁出现304状态码的原因

原标题&#xff1a;网站频繁出现304状态码的原因很多SEOER经常说网站日志反回值304是怎么回事&#xff1f;经常会碰到站长们抱怨蜘蛛抓取返回码老是304状态&#xff0c;且抓取的次数越来越少的问题。搜索引擎为了自身的用户体验&#xff0c;会想尽办法来提高检索调用率、准确性…

接口测试学习——操作MySQL

第一步要导入第三方的jar包。&#xff08;jemeter不能直接连接MySQL&#xff09; 操作方法就是点击“测试计划”&#xff0c;右侧展开的页面中选择【浏览】&#xff0c;选择MySQL的jar包。导入即可。 第二步&#xff1a;创建数据库链接的配置&#xff1a;MySQL的路径URL、端口号…

html5网页自动滚动,Html5 滚动穿透的方法

问题背景&#xff1a;网站需要在移动端完成适配,针对移动端H5以及web端采用的都是bluma这种flex布局解决方案在H5中使用的列表采用的是 react-virtualized 来绘制表格为了展示表格中单行数据的具体详情&#xff0c;通常的解决方案是采用新页面或者是弹窗来完成。这里采用的是弹…

html代码 打开本地文件,打开本地HTML文件

我在布局中有一个textview(名为-t_c)&#xff0c;代码为&#xff1a; -android:id"id/GoToTCContacting"android:layout_width"360dp"android:layout_height"wrap_content"android:layout_marginLeft"2dp"android:layout_marginRight&…

元组,字符串的基础

元组&#xff0c;字符串&#xff0c; a(1,2,3,4,56,) type(a) print(type(a)) #元祖就是不可变列表 usernameinput("username:") if username.strip()"spencer": #语句能够让输入的内容多按空格&#xff1a;移除空白print("welcome") names"…

mac如何看html5视频播放器,苹果Mac系统看HTML5视频教程介绍

上一回&#xff0c;小编教了大家一个Mac用 HTML5 免费看优酷和土豆等付费视频&#xff0c;这回小编又找到一个用HTML5看视频的好方法&#xff0c;很多很好用的资源&#xff0c;你可以在Mac上看各种地方台的直播以及乐视、凤凰卫视、TVB、东森等港澳台电视节目哦&#xff01;大部…

node转发请求 .csv格式文件下载 中文乱码问题 + 文件上传笔记

用户无法直接访问后台接口 需要node端转发请求 并将数据以.csv文件格式生成以供客户端下载。 很不幸出现了中文乱码的问题 挖了各种坟帖&#xff0c;下了各种依赖包&#xff0c;csv、json2csv、bufferHelper、iconv-lite等等 多次尝试后 发现真正起作用的只有iconv-lite这个库 …

html中设置负边距的意义,css负边距之详解

自从1998年CSS2作为推荐以来&#xff0c;表格的使用渐渐退去&#xff0c;成为历史。正因为此&#xff0c;从那以后CSS布局成为了优雅代码的代名词。对于所有设计师使用过的CSS概念&#xff0c;负边距作为最少讨论到的定位方式要记上一功。这就像是在线纹身-每个人都会做&#x…

warning: expression result unuesd 可能原因是函数忘了加括号,

转载于:https://www.cnblogs.com/chulin/p/9082833.html

计算机怎样辅助英语听力教学方法有哪些,计算机辅助教学在英语听力中的运用.doc...

计算机辅助教学在英语听力中的运用.docPAGEPAGE 5计算机辅助教学在英语听力中的运用摘要&#xff1a;随着现代科学技术与电脑的发展&#xff0c;计算机辅助教学比以往运用的更加广泛&#xff0c;在计算机的帮助下&#xff0c;我们可以把大量的网上信息运用到英语教学中&#xf…

vue基础18(vue-cli脚手架项目中组件的使用)

vue-cli脚手架项目中组件的使用 在webpack-simple模板中&#xff0c;包括webpck模板。一个.vue文件就是一个组件。 为什么会这样呢&#xff1f;因为webpack干活了&#xff01;webpack的将我们所有的资源文件进行打包。同时webpack还能将我们的html&#xff08;template&#xf…

计算机科学与导论期末论文,计算机科学与导论论文3

由下到上按左到右的顺序排列&#xff0c;则11用二进制表示为1011。4.3.3整数的机器数表达方法A、一般表示法首先将数转换成二进制&#xff1b;忽略符号&#xff0c;左侧用0补充空位至指定位数-1&#xff1b;如果是正数&#xff0c;在最高位加0&#xff0c;如果是负数则加1。例如…

js和layerjs配合实现的拖拽表格列

前几天想着实现表格列的拖拽 写了个例子 一直不完美 经过修改感觉还算完美了 拖拽过程不会复制文字并且还能实现layerjs本身自带的表格排序功能。 1、首先引入layer.css jquery layui.all.js 2、布局页面 <div class"divT"> <table class"l…