android吸附菜单,Android仿微博、人人Feed详情页吸附导航栏

仿微博、人人的feed详情页面:Listview上下滑动,导航栏view可吸附在顶部的效果。

一、实现效果

上图:

7fe153e8d237

效果图.gif

欢迎拍砖,拍拍更进步。

没有对比,怎么会有伤害,下面是 微博、人人的Feed详情页:

7fe153e8d237

微博、人人Feed详情页.jpeg

二、实现原理

1、

实例化两个一样的导航栏view,一个放在页面根布局顶部的view1,另一个放在ListView的headerView中的view2,在OnScrollListener的onScroll方法中,检测view2在屏幕中的位置是不是滑动到了顶部,决定顶部view1的显示与隐藏,以达到看起来只有一个导航栏view显示的效果;

2、

为了保持两个导航栏view的状态同步,使用了观察者模式;

3、

导航栏中的Tab切换,即切换ListView的adapter,并且记录滑动的位置信息。

三、UML图

7fe153e8d237

UML图.png

StickyNavHostSubject:它把所有的自定义导航栏view的引用保存到一个list里。AbstractSubject提供了接口,可以增加和删除观察者对象。

StickyNavHost:自定义的导航栏view,继承自ViewGroup,可以根据具体需求自行更改显示的布局、样式等。

NavListViewScollListener:需要为ListView设置的滑动事件,封装了对吸附导航栏显示、隐藏的逻辑。

MainActivity:用于演示demo,包含了对导航栏view的初始化,以及切换tab的操作等。

三、具体细节

1、

NavListViewScollListener的onScroll()方法:

@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

//处理了root导航栏的显示与隐藏, 本质上只是控制root导航栏的显示

//而在listView的headerView中的导航栏不做处理,因为它会随着listView的滑动自行滑出页面

if (NavBean.IS_NEED_ATTACH && rootView != null && nav != null) {

rootView.getLocationOnScreen(rootLocation);

headView.getLocationOnScreen(headLocation);

//根据两者在屏幕中的location位置信息,决定root导航栏的显示与隐藏

if (rootLocation[1] > headLocation[1]) {

rootView.setVisibility(View.VISIBLE);

} else {

rootView.setVisibility(View.INVISIBLE);

}

//记录当前listView的滑动位置

nav.setFirstVisibleItem(firstVisibleItem);

nav.setTopDistance((view.getChildAt(0) == null) ? 0 : view.getChildAt(0).getTop());

}

}

2、

MainActivity中初始化操作:

private void initNavsView() {

initNavsData();

stickyNavHostRoot.setTabItemClickListener(this);//设置点击回调

stickyNavHostHead.setTabItemClickListener(this);//设置点击回调

stickyNavHostRoot.setShowTopLine(false);

stickNavHostSubject = new StickNavHostSubject();

stickNavHostSubject.attachObserver(stickyNavHostRoot);//观察者模式

stickNavHostSubject.attachObserver(stickyNavHostHead);

NavBean[] sortedNavs = new NavBean[mNavs.size()];//指定导航栏的排列顺序

sortedNavs[0] = mNavs.get(NavBean.TYPE_REPOST);

sortedNavs[1] = mNavs.get(NavBean.TYPE_COMMENT);

sortedNavs[2] = mNavs.get(NavBean.TYPE_LIKE);

stickNavHostSubject.initTabData(sortedNavs);

scrollListener = new NavListViewScrollListener(stickyNavHostRoot, stickyNavHostHead);

mListView.setOnScrollListener(scrollListener);//为listView设置滑动监听,内部处理了吸附view的显示与隐藏

}

protected void initNavsData() {

mNavs = new SparseArray<>(NAV_LENGTH);

mNavs.put(NavBean.TYPE_REPOST, new NavBean(NavBean.TYPE_REPOST, new TestAdapter(20, "我是转发", this)));

mNavs.put(NavBean.TYPE_COMMENT, new NavBean(NavBean.TYPE_COMMENT, new TestAdapter(20, "我是评论", this)));

mNavs.put(NavBean.TYPE_LIKE, new NavBean(NavBean.TYPE_LIKE, new TestAdapter(20, "我是赞", this)));

}

private void initView() {

mListView = (ListView) findViewById(R.id.list_view);

stickyNavHostRoot = (StickyNavHost) findViewById(R.id.sticky_nav_layout);

stickyNavHostRoot.setVisibility(View.INVISIBLE);

View testHeaderView = LayoutInflater.from(this).inflate(R.layout.listview_head_view_test_layout, null);

mListView.addHeaderView(testHeaderView);

View inflateView = LayoutInflater.from(this).inflate(R.layout.sticky_nav_host_layout, null);

stickyNavHostHead = (StickyNavHost) inflateView.findViewById(R.id.sticky_nav_layout);

stickyNavHostHead.setVisibility(View.VISIBLE);

mListView.addHeaderView(stickyNavHostHead);

STICKY_POSITION_IN_HEADER = mListView.getHeaderViewsCount();

}

3、

MainActivity中点击切换导航栏Tab的回调:

@Override

public void onTabItemSelected(@NavBean.TYPE int type) {

NavBean currNav = mNavs.get(type);

stickNavHostSubject.setSelectedType(type);//事件分发给注册者,注册者进行相应的变化

if (currNav.type == NavBean.TYPE_CURRENT)//等于当前选中的tab,可以屏蔽掉

return;

NavBean.TYPE_CURRENT = currNav.type;

scrollListener.setNav(currNav);

mListView.setAdapter(currNav.adapter);

if (stickyNavHostRoot.getVisibility() == View.VISIBLE) {//吸附在顶部的rootView正在展示

if (currNav.getFirstVisibleItem() < STICKY_POSITION_IN_HEADER)

mListView.setSelectionFromTop(STICKY_POSITION_IN_HEADER, stickyNavHostRoot.getHeight() - 2);

else

mListView.setSelectionFromTop(currNav.getFirstVisibleItem(), currNav.getTopDistance());

} else {//吸附在顶部的rootView没有展示,说明在切换导航栏的时候是不需要进行滑动的,保持上次的位置即可

mListView.setSelectionFromTop(NavBean.firstVisibleItemUniversal, NavBean.topDistanceUniversal);

}

}

4、

StickyNavHostSubject做的事情就很简单了,和常见的观察者模式没区别:

public class StickNavHostSubject extends AbstractSubject {

private List observers;

public StickNavHostSubject() {

observers = new ArrayList<>();

}

public void attachObserver(IStickyNavHostObserver observer) {

observers.add(observer);

}

public void detachObserver(IStickyNavHostObserver observer) {

observers.remove(observer);

}

@Override

public void initTabData(NavBean[] navs) {

for (IStickyNavHostObserver observer : observers)

observer.initTabData(navs);

}

@Override

public void refreshTabData(NavBean nav) {

for (IStickyNavHostObserver observer : observers)

observer.refreshTabData(nav);

}

@Override

public void setSelectedType(@NavBean.TYPE int type) {

for (IStickyNavHostObserver observer : observers)

observer.setSelectedType(type);

}

@Override

public void setSelectedPosition(int position) {

for (IStickyNavHostObserver observer : observers)

observer.setSelectedPosition(position);

}

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

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

相关文章

android 居右属性,使用layoutDirection属性设置布局靠左或靠右

通过设置layoutDirection属性值为mx.core.LayoutDirection.RTL(右到左)或mx.core.LayoutDirection.LTR(左到右)&#xff0c;使布局为靠左或靠右(如下图)。该属性可设置3种值&#xff0c;LayoutDirection.RTL、LayoutDirection.LTR和null(ILayoutDirectionElement时)/undefined(…

【CodeForces - 255B】Code Parsing(思维,字符串)

题干&#xff1a; Little Vitaly loves different algorithms. Today he has invented a new algorithm just for you. Vitalys algorithm works with string s, consisting of characters "x" and "y", and uses two following operations at runtime: …

【CodeForces - 255C】Almost Arithmetical Progression (dp,离散化)

题干&#xff1a; Gena loves sequences of numbers. Recently, he has discovered a new type of sequences which he called an almost arithmetical progression. A sequence is an almost arithmetical progression, if its elements can be represented as: a1  p, wh…

Android手机mm开头的大文件,[2018年最新整理]2Android源代码编译命令m和mm和mmm以及make分析.doc...

[2018年最新整理]2Android源代码编译命令m和mm和mmm以及make分析老罗的新浪微博&#xff1a;/shengyangluo&#xff0c;欢迎关注&#xff01;在前文中&#xff0c;我们分析了Android编译环境的初始化过程。Android编译环境初始化完成后&#xff0c;我们就可以用m/mm/mmm/make命…

【CodeForces - 349C】Mafia(思维模拟,优秀的二分)

题干&#xff1a; One day n friends gathered together to play "Mafia". During each round of the game some player must be the supervisor and other n - 1 people take part in the game. For each person we know in how many rounds he wants to be a pl…

android新材料设计,android - 如何实现新材料BottomAppBar为BottomNavigationView - SO中文参考 - www.soinside.com...

解决了基本上&#xff0c;而不是试图迫使菜单的资源&#xff0c;我需要的布局&#xff0c;我用这个方法&#xff0c;而不是&#xff0c;我只是把使用“空”元素作为dglozano建议BottomAppBar内的LinearLayout。使用?attr/selectableItemBackgroundBorderless我也能做到这一点实…

【CodeForces - 1A】Theatre Square(水题,几何)(CODEFORCES,梦的开始)

题干&#xff1a; Theatre Square in the capital city of Berland has a rectangular shape with the size n  m meters. On the occasion of the citys anniversary, a decision was taken to pave the Square with square granite flagstones. Each flagstone is of the …

html教程是语音版,【HTML教程】HTML 语言简介

标签是一个容器标签&#xff0c;用于放置网页的主体内容。浏览器显示的页面内容&#xff0c;都是放置在它的内部。它是的第二个子元素&#xff0c;紧跟在后面。网页标题hello world

【POJ - 1664】放苹果 (递归经典题 或 dp 或 母函数)

题干&#xff1a; 把M个同样的苹果放在N个同样的盘子里&#xff0c;允许有的盘子空着不放&#xff0c;问共有多少种不同的分法&#xff1f;&#xff08;用K表示&#xff09;5&#xff0c;1&#xff0c;1和1&#xff0c;5&#xff0c;1 是同一种分法。 Input 第一行是测试数据…

html文本下一页,Javascript html2canvas + jsPDF 导出PDF,解决一半文字在上一页一半文字在下一页的问题...

var pdfContent document.getElementById("pdfDiv");var width pdfContent.offsetWidth; //获取dom 宽度var height pdfContent.offsetHeight; //获取dom 高度var canvas document.createElement("canvas"); //创建一个canvas节点var scale 3; //定义…

无法设置html过渡效果,html – CSS3过渡显示无阻止过度滚动

我假设你的弹出窗口是绝对定位的,所以你可以做以下事情&#xff1a;>隐藏时,将弹出窗口设置为巨大的负值.这会将其移出屏幕并摆脱滚动条.>在悬停时,将顶部设置为正确的值并转换不透明度值.>确保CSS转换规则仅适用于opacity属性.HTMLPopup go nowMy cats breath smells…

ACM 题目分类POJ(自用,精)

详情见博客&#xff1a;http://exp-blog.com/2018/06/28/pid-38/ 和博客https://blog.csdn.net/a1dark/article/details/11714009/ http://exp-blog.com/2018/06/10/pid-136/ https://blog.csdn.net/lyy289065406/article/details/6642573

html表格全屏显示,tableView滑动全屏显示

今天要分享的一个效果是在一个页面弹出视图展示一个tableview&#xff0c;然后手指滑动tableview时&#xff0c;视图随着tableview偏移量增加而慢慢增加&#xff0c;到达临界时&#xff0c;全屏显示&#xff0c;然后再次向下滑动时&#xff0c;当偏移量到达临界点&#xff0c;视…

【 CodeForces - 864B】Polycarp and Letters(水题,字符串,有坑)

题干&#xff1a; Polycarp loves lowercase letters and dislikes uppercase ones. Once he got a string sconsisting only of lowercase and uppercase Latin letters. Let A be a set of positions in the string. Lets call it pretty if following conditions are met:…

计算机网络65535,计算机网络1

1.网络基础&#xff1a;1.1 IT行业铁三角&#xff1a;os&#xff0c;web&#xff0c;sql 不管是哪个IT岗位都应该懂&#xff0c;1.2 开发铁三角&#xff1a;语言&#xff0c;数据结构算法&#xff0c;数据模式1.3 测试铁三角&#xff1a;需求&#xff0c;搭环境和设计用例&…

【CodeForces - 864C】Bus (模拟,有坑)

题干&#xff1a; A bus moves along the coordinate line Ox from the point x  0 to the point x  a. After starting from the point x  0, it reaches the point x  a, immediately turns back and then moves to the point x  0. After returning to the point…

大量html乱码seo,HTTPS改造之后网页错位乱码,影响SEO和正常访问,应该这样改

有一些朋友可能不太知道https改造怎么做&#xff0c;就学着网站的步骤进行&#xff0c;实际操作过程中可能会遇到很多问题。比如说有的会出现网页错位、页面乱码、后台功能无法使用的情况。昨天我们就有一个客户他自己做了https改造&#xff0c;但是造成后台无法上传图片的情况…

【NOIP2013积木大赛,NOIP2018铺设道路】积木大赛(思维,贪心)

题干&#xff1a; 题目描述 春春幼儿园举办了一年一度的“积木大赛”。今年比赛的内容是搭建一座宽度为nn的大厦&#xff0c;大厦可以看成由n块宽度为1的积木组成&#xff0c;第i块积木的最终高度需要是h_ihi​。 在搭建开始之前&#xff0c;没有任何积木&#xff08;可以看…

微型计算机中最小的单位,微型计算机中最小的数据单位是

微型计算机中最小的数据单位是比特。微型计算机&#xff0c;是指由微处理器作为CPU的计算机。由大规模集成电路组成的、体积较小的电子计算机。由微处理机(核心)、存储片、输入和输出片、系统总线等组成。特点是体积小、灵活性大、价格便宜、使用方便。这类计算机的普遍特征就是…

【每日算法】【图论】【最小边覆盖 最小路径覆盖 最小顶点覆盖 最大独立集 最大团】

最小边覆盖 最大独立集 |V| - 最大匹配数 这个是在原图是二分图上进行的 最小路径覆盖和最小边覆盖不同&#xff0c;不要求给的图是二分图&#xff0c;而是要求是N x N的有向图&#xff0c;不能有环&#xff0c;然后根据原图构造二分图&#xff0c;构造方法是将点一分为二&am…