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

Android实现网易严选标签栏滑动效果

这篇文章主要为大家详细介绍了Android实现网易严选标签栏滑动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

标签栏是一个非常常见的控件,似乎也是一个比较简单的控件,但如果在标签下方加个下划线的话,就还是可以玩出挺多花来的。

网易严选的标签栏就做的很不错,里面隐藏着诸多细节:

  • 手动滑动页面,下划线会跟着滑动。
  • 选择一个标签后,下划线会有滑动过去的动画。
  • 选择最左端或最右端的标签,标签栏会进行滑动,使得标签向中间靠拢(如果可以滑的话)。

仔细分析下,需要在简单标签栏的基础上实现以下逻辑:

  • 画出下划线。
  • 监听手动滑动页面事件,实时更新下划线位置。
  • 切换标签时,开始下划线滑动的动画,并判断是否要同时滑动标签栏。

我做了一个样例程序,其中的较难点在于计算下划线的位置,和下划线的动画效果。

// 根据当前选定的tab,得到indicator应该移动到的位置 
private Pair getIndicatorTargetLeftRight(int position, float positionOffset) { 
  View tab = tabsContainer.getChildAt(position); 
  Pair indicator = getIndicatorLeftRight(tab); 
  float targetLeft = indicator.first; 
  float targetRight = indicator.second; 
  // 如果positionOffset不为0,indicator正处于两个tab之间,需进行加权计算得到它的位置 
  if (positionOffset > 0f && position  indicatorForNextTab = getIndicatorLeftRight(nextTab); 
    float left = indicatorForNextTab.first; 
    float right = indicatorForNextTab.second; 
    targetLeft = (positionOffset * left + (1f - positionOffset) * targetLeft); 
    targetRight = (positionOffset * right + (1f - positionOffset) * targetRight); 
  } 
  return new Pair<>(targetLeft, targetRight); 
} 
 
private Pair getIndicatorLeftRight(View tab) { 
  float left = tab.getLeft(); 
  float right = tab.getRight(); 
  if (indicatorMode == IndicatorMode.WRAP && tab instanceof TextView) { 
    TextView tabTextView = (TextView) tab; 
    paint.setTextSize(tabTextView.getTextSize()); 
    float textLength = paint.measureText(tabTextView.getText().toString()); 
    float middle = (left + right) / 2f; 
    left = middle - textLength / 2f; 
    right = middle + textLength / 2f; 
  } 
  return new Pair<>(left, right); 
} 

上面是计算下划线位置的代码,通过传入在onPageScrolled()中获得的position和positionOffset,计算下划线是在某一个标签下,或者某两个标签之间的位置。需要注意的是,由于各标签的长度可能不一,所以下划线的长度在滑动中也可能发生变化,所以需分别计算下划线的left和right。

private boolean isAnimateRunning = false; 
private static final String TARGET_LEFT = "targetLeft"; 
private static final String TARGET_RIGHT = "targetRight"; 
 
private void startIndicatorAnimate(final float targetLeft, final float targetRight) { 
  // 在indicator超出屏幕范围时,让其从屏幕边界处开始移动 
  float move = 0; 
  if (indicatorCurrentRight  getScrollX() + DimenUtil.getScreenWidth(getContext())) { 
    move = getScrollX() + DimenUtil.getScreenWidth(getContext()) - indicatorCurrentLeft; 
  } 
  indicatorCurrentLeft += move; 
  indicatorCurrentRight += move; 
 
  PropertyValuesHolder valuesHolderLeft = PropertyValuesHolder.ofFloat( 
      TARGET_LEFT, indicatorCurrentLeft, targetLeft); 
  PropertyValuesHolder valuesHolderRight = PropertyValuesHolder.ofFloat( 
      TARGET_RIGHT, indicatorCurrentRight, targetRight); 
  ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(valuesHolderLeft, valuesHolderRight) 
      .setDuration(SCROLL_DURATION); 
  animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
    @Override 
    public void onAnimationUpdate(ValueAnimator animation) { 
      if (indicatorCurrentLeft != targetLeft) { 
        indicatorCurrentLeft = (float) animation.getAnimatedValue(TARGET_LEFT); 
      } 
      if (indicatorCurrentRight != targetRight) { 
        indicatorCurrentRight = (float) animation.getAnimatedValue(TARGET_RIGHT); 
      } 
      if (indicatorCurrentLeft == targetLeft && indicatorCurrentRight == targetRight) { 
        isAnimateRunning = false; 
      } 
      invalidate(); 
    } 
  }); 
  animator.start(); 
  isAnimateRunning = true; 
} 

这是切换标签时下划线运行滑动动画的代码,使用ValueAnimator实现,并且对下划线超出边界的情况做了特殊处理,以防止滑动距离过大时,滑动速度过快。

更多的细节,请见https://github.com/wlkdb/page_sliding

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文基于对相关论文和开源代码的研究,详细介绍了LOAM(激光雷达里程计与建图)的工作原理,并对其关键技术进行了分析。 ... [详细]
  • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
    来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文介绍如何使用 Sortable.js 库实现元素的拖拽和位置交换功能。Sortable.js 是一个轻量级、无依赖的 JavaScript 库,支持拖拽排序、动画效果和多种插件扩展。通过简单的配置和事件处理,可以轻松实现复杂的功能。 ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文详细介绍了如何在 Spring Boot 应用中通过 @PropertySource 注解读取非默认配置文件,包括配置文件的创建、映射类的设计以及确保 Spring 容器能够正确加载这些配置的方法。 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文介绍了如何使用JQuery实现省市二级联动和表单验证。首先,通过change事件监听用户选择的省份,并动态加载对应的城市列表。其次,详细讲解了使用Validation插件进行表单验证的方法,包括内置规则、自定义规则及实时验证功能。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
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社区 版权所有