热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Android实现App中导航Tab栏悬浮的功能

相信大家在玩手机的过程中应该会注意到很多的app都有这种功能,比如说外卖达人常用的“饿了么”。所以这篇文章给大家分享了Android如何实现app中的导航Tab栏悬浮的功能,有需要的朋友们可以参考借鉴。

首先是“饿了么”导航Tab栏悬浮的效果图。

大家可以看到上图中的“分类”、“排序”、“筛选”会悬浮在app的顶部,状态随着ScrollView(也可能不是ScrollView,在这里姑且把这滑动的UI控件当作ScrollView吧)的滚动而变化。像这种导航Tab栏悬浮的作用相信大家都能体会到,Tab栏不会随着ScrollView等的滚动而被滑出屏幕外,增加了与用户之间的交互性和方便性。

看到上面的效果,相信大家都跃跃欲试了,那就让我们开始吧。

首先大家要明白一点:Tab栏的状态变化是要监听ScrollView滑动距离的。至于如何得到ScrollView的滑动距离?可以看看另一篇: 《Android中ScrollView实现滑动距离监听器的方法》 ,这里就不过多叙述了。

好了,根据上面的就得到了对ScrollView滑动的监听了。接下来要思考的问题就是如何让Tab栏实现悬浮的效果呢?这里给出的方法有两种,第一种就是使用WindowManager来动态地添加一个View悬浮在顶部;第二种就是随着ScrollView的滑动不断重新设置Tab栏的布局位置。

我们先来看看第一种实现方法,首先是xml布局了。

Activity的布局,activity_main.xml:

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  

    

    

  

  

    

      

      

      

      

      

      

      

      

      

      

      

      


      

      

      

      
      
    
  

Tab栏的布局,tab_layout.xml:

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  

  

  

上面布局中的很多空白LinearLayout主要是拉长ScrollView,效果图就是这样的:

然后我们来看看onCreate(Bundle savedInstanceState):

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  getSupportActionBar().hide();
  setContentView(R.layout.activity_main);
  mScrollView = (MyScrollView) findViewById(R.id.mScrollView);
  mScrollView.setOnScrollListener(this);
  ll_tab = (LinearLayout) findViewById(R.id.ll_tab);
  windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
}

我们先在onCreate(Bundle savedInstanceState)中给ScrollView添加了滑动距离监听器以及得到了一个windowManager的对象。还有一点需要注意的是:我们调用了getSupportActionBar().hide();去掉了标题栏(MainActivity继承了AppCompatActivity)。这是因为标题栏的存在导致了在计算悬浮窗y轴的值时要额外加上标题栏的高度(当然你也可以保留标题栏,然后计算时再加上标题栏的高度^_^!)。

然后在onWindowFocusChanged(boolean hasFocus)得到Tab栏的高度、getTop()值等,以便下面备用。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
  super.onWindowFocusChanged(hasFocus);
  if (hasFocus) {
    tabHeight = ll_tab.getHeight();
    tabTop = ll_tab.getTop();
    scrollTop = mScrollView.getTop();
  }
}

之后在滑动监听器的回调方法onScroll(int scrollY)中来控制显示还是隐藏悬浮窗。

@Override
public void onScroll(int scrollY) {
  Log.i(TAG, "scrollY = " + scrollY + ", tabTop = " + tabTop);
  if (scrollY > tabTop) {
 // 如果没显示
    if (!isShowWindow) {
      showWindow();
    }
  } else {
 // 如果显示了
    if (isShowWindow) {
      removeWindow();
    }
  }
}

上面的代码比较简单,不用我过多叙述了。下面是removeWindow() showWindow()两个方法:

// 显示window
private void removeWindow() {
  if (ll_tab_temp != null)
    windowManager.removeView(ll_tab_temp);
  isShowWindow = false;
}

// 移除window
private void showWindow() {
  if (ll_tab_temp == null) {
    ll_tab_temp = LayoutInflater.from(this).inflate(R.layout.tab_layout, null);
  }
  if (layoutParams == null) {
    layoutParams = new WindowManager.LayoutParams();
    layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE; //悬浮窗的类型,一般设为2002,表示在所有应用程序之上,但在状态栏之下
    layoutParams.format = PixelFormat.RGBA_8888;
    layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; //悬浮窗的行为,比如说不可聚焦,非模态对话框等等
    layoutParams.gravity = Gravity.TOP; //悬浮窗的对齐方式
    layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
    layoutParams.height = tabHeight;
    layoutParams.x = 0; //悬浮窗X的位置
    layoutParams.y = scrollTop; //悬浮窗Y的位置
  }
  windowManager.addView(ll_tab_temp, layoutParams);
  isShowWindow = true;
}

这两个方法也很简单,而且有注释,相信大家可以看懂。

最后,不要忘了在AndroidManifest.xml里申请显示悬浮窗的权限:

到这里,整体的代码就这些了。一起来看看效果吧:

值得注意的是:如果用这种方法来实现Tab栏悬浮功能有一个缺点,那就是如果该app没有被赋予显示悬浮窗的权限,那么该功能就变成鸡肋了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对各位Android开发者们的学习或者工作能有所帮助,如果有疑问大家可以留言交流。


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文是关于自学Android的笔记,包括查看类的源码的方法,活动注册的必要性以及布局练习的重要性。通过学习本文,读者可以了解到在自学Android过程中的一些关键点和注意事项。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
author-avatar
問露旧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有