热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android仿今日头条APP实现下拉导航选择菜单效果

这篇文章主要为大家详细介绍了Android仿今日头条APP实现下拉导航选择菜单效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了在Android中如何实现下拉导航选择菜单效果的全过程,供大家参考,具体内容如下

关于下拉导航选择菜单效果在新闻客户端中用的比较多,当然也可以用在其他的项目中,这样可以很方便的选择更多的菜单。我们可以让我们的应用顶部有左右滑动或进行切换的导航菜单,也可以为了增强用户体验在应用中添加这样的下拉导航选择菜单效果。

关于它的实现原理,其实也是挺简单的,就是使用PopupWindow来进行展现,在显示时控制其高度并配置以相应的动画效果。在PopupWindow中我使用GridView来控制里面的菜单项,每个菜单项对应相应的图片和文字。当然了,也有其他的实现方式。为了大家能够清楚的理解,让我们先看下效果图,如下所示: 

  

 以上就是我实现的示例图,大家已经看到了,就是点击应用顶部中间的文字时展现出来,在我们点击其中一项菜单时隐藏并加载相应菜单的内容,同时该菜单处于选中状态。好了,下面就让我们开始我们的实现过程,还是先看下程序结构图吧:

在程序结构图中,PulldownMenuView是对PopupWindow进行的封装类,PulldownMenuItem是菜单项类,这是两个重要的类。在我们点击应用顶部中间的文字时,要进行展现,展现的同时,要实现对菜单的初始化工作,首先是初始化数据,其主要代码如下:

  /**
 * 初始化数据,将数据加载到对应的View中
 */
 private void initData(){
 PulldownMenuItem item = new PulldownMenuItem(context);
 item.setMenuAlign(menuAlign);
 item.setMenuTextColor(menuTextColor);
 item.setMenuTextSize(menuTextSize);
 int txtLength = menuTexts.length;
 int imgLength = menuImageRes.length;
 
 if (txtLength != 0 && imgLength != 0){
 for (int i = 0; i 

currentItem代表当前的选择项,在初始化数据过程中,需要检测哪项菜单被选中了,如果某项菜单被选中,则在展开时需要将该项菜单图片和文字颜色设置成相应状态,表示该项菜单被选中。在初始化过程中分为三种情况:第一种是菜单项既有图片也有文字;第二种是菜单项只有文字;第三种是菜单项只有图片;所以在上面代码中需要进行相应判断。上面是初始化菜单中的数据,下面是初始化菜单中的内容:

 /**
 * 初始化菜单内容
 * @param context
 * @param columns 菜单的列数
 * @return
 */
 private GridView getMenuGirdView(Context context, int columns){
 if (menuMenuItems.isEmpty()){
 // 初始化菜单数据
 initData();
 }
 
 if (null != menuGridView){
 return menuGridView;
 }
 
 GridView gridView = new GridView(context);
 gridView.setLayoutParams(new LinearLayout.LayoutParams(
 ViewGroup.LayoutParams.MATCH_PARENT, 
 ViewGroup.LayoutParams.MATCH_PARENT));
 // 设置数据适配器
 gridView.setAdapter(new PulldownMenuAdapter(menuMenuItems));
 gridView.setVerticalSpacing(1);
 gridView.setNumColumns(columns);
 gridView.setGravity(Gravity.CENTER);
 gridView.setVerticalScrollBarEnabled(false);
 
 if (menuBackground != 0){
 gridView.setBackgroundResource(menuBackground);
 }
 
 if (menuSelector != -1){
 gridView.setSelector(menuSelector);
 }
 
 gridView.setHorizontalScrollBarEnabled(false);
 setMenuListener(gridView);
 
 return gridView;
 }

初始化菜单之后,就需要我们菜单中相应的数据,设置数据比较容易,只需要三个数组即可:第一个数组代表菜单项文字内容;第二个数组代表菜单项图片资源,第三个数组代表菜单项被选中的图片资源。如下代码:

 /**
 * 新闻菜单项图片资源
 */
 public final static int[] newsImageRes = {
 R.drawable.ic_menu_toutiao,R.drawable.ic_menu_gn,
 R.drawable.ic_menu_gj,R.drawable.ic_menu_sh,
 R.drawable.ic_menu_sport,R.drawable.ic_menu_nba,
 R.drawable.ic_menu_blog,R.drawable.ic_menu_book,
 R.drawable.ic_menu_yule,R.drawable.ic_menu_mil,
 R.drawable.ic_menu_cj,R.drawable.ic_menu_tech,
 R.drawable.ic_menu_mobile,R.drawable.ic_menu_women,
 R.drawable.ic_menu_car,R.drawable.ic_menu_house
 };
 
 /**
 * 新闻菜单项选中图片资源
 */
 public final static int[] newsImageResPress = {
 R.drawable.ic_menu_toutiao_press,R.drawable.ic_menu_gn_press,
 R.drawable.ic_menu_gj_press,R.drawable.ic_menu_sh_press,
 R.drawable.ic_menu_sport_press,R.drawable.ic_menu_nba_press,
 R.drawable.ic_menu_blog_press,R.drawable.ic_menu_book_press,
 R.drawable.ic_menu_yule_press,R.drawable.ic_menu_mil_press,
 R.drawable.ic_menu_cj_press,R.drawable.ic_menu_tech_press,
 R.drawable.ic_menu_mobile_press,R.drawable.ic_menu_women_press,
 R.drawable.ic_menu_car_press,R.drawable.ic_menu_house_press
 };
 
 /**
 * 新闻菜单项文字
 */
 public final static String[] newsMenuTexts = {
 "今日头条","国内","国际","社会","体育","NBA","博客","读书",
 "娱乐","军事","财经","科技","手机","女性","汽车","房产"
 };

菜单项使用GridView实现,我们还需要设置每个菜单项的监听事件,在选中一项菜单后或是点击返回键或点击菜单键时实现隐藏,代码如下:

 /**
 * 设置菜单项监听事件
 * @param gridView
 */
 private void setMenuListener(GridView gridView){
 if (null == gridView.getOnItemClickListener()){
 gridView.setOnItemClickListener(new OnItemClickListener(){
 @Override
 public void onItemClick(
 AdapterView<&#63;> parent, 
 View view,
 int position, 
 long id){
 if (null != menuItemListener){
 menuItemListener.onMenuItemClick(parent, view, position);
 }
 
 hide();
 }
 });
 }
 
 // 按返回键或菜单键隐藏菜单
 gridView.setOnKeyListener(new OnKeyListener(){
 @Override
 public boolean onKey(View v, int keyCode, KeyEvent event){
 if (event.getAction() == KeyEvent.ACTION_DOWN){
 switch (keyCode){
 case KeyEvent.KEYCODE_BACK:
 case KeyEvent.KEYCODE_MENU:
 hide();
 break;
 }
 }
 
 return false;
 }
 });
 }

在PulldownMenuView类中的show()和hide()方法中,主要是实现菜单的显示与隐藏。在show()方法中,要计算每行存放的菜单数、设置相应的高度、菜单整体的背景、动画效果、菜单显示的位置等效果。具体不再详述。
我们在显示下拉导航选择菜单前还需要配置菜单相应的参数,比如显示位置、背景图片、高度等。这就是在MenuUtility类中要实现的,代码如下:

package com.navigation.utility;

import com.navigation.acitvity.R;
import com.navigation.control.PulldownMenuView;

import android.content.Context;
import android.view.View;

/**
 * PulldownMenuView基本操作类
 * @Description: PulldownMenuView基本操作类

 * @File: PulldownMenuUtility.java

 * @Package com.navigation.utility

 * @Author Hanyonglu

 * @Date 2012-7-30 上午11:41:04

 * @Version V1.0
 */
public class MenuUtility {
 private Context cOntext= null;
 // PulldownMenuView对象
 private PulldownMenuView menu = null;
 // 图片资源
 private int[] imageRes = null;
 // 文字内容
 private String[] texts = null;
 // 菜单高度
 private int height = 0;
 private View anchorView = null;
 
 /**
 * 默认的构造器
 */
 public MenuUtility() {
 // TODO Auto-generated constructor stub
 }
 
 /**
 * 带Context的构造器
 * @param context
 */
 public MenuUtility(Context context) {
 // TODO Auto-generated constructor stub
 this(context,null,null,0,null);
 }
 
 /**
 * 带多参的构造器
 * @param context
 * @param imageRes
 * @param texts
 */
 public MenuUtility(Context context,int[] imageRes,String[] texts,int height,View anchorView){
 this.cOntext= context;
 this.imageRes = imageRes;
 this.texts = texts;
 this.height = height;
 this.anchorView = anchorView;
 }
 
 /**
 * 设置图片资源
 * @param imageRes
 */
 public void setImageRes(int[] imageRes){
 this.imageRes = imageRes;
 }
 
 /**
 * 设置文字内容
 * @param texts
 */
 public void setTexts(String[] texts){
 this.texts = texts;
 }
 
 /**
 * 设置高度
 * @param height
 */
 public void setHeight(int height){
 this.height = height;
 }
 
 /**
 * 设置显示的位置
 * @param anchor
 */
 public void setAnchorView(View anchor){
 anchorView = anchor;
 }
 
 /**
 * 获取PulldownMenuView对象
 * 以下拉的形式展现出来菜单
 * @return
 */
 public PulldownMenuView getPulldownMenuView(String currentItem){
 PulldownMenuView menu = new PulldownMenuView(context);
 menu.setImageRes(imageRes);
 menu.setMenuText(texts);
 menu.setHeight(height);
 menu.setAnchorView(anchorView);
 menu.setCurrentItem(currentItem);
 menu.setBackground(R.drawable.navigation_bg);
 
 return menu;
 }
 
 /**
 * 获取PulldownMenuView对象
 * 以向上弹出的方式展现出来菜单
 * @return
 */
 public PulldownMenuView getPopupMenuView(){
 PulldownMenuView menu = new PulldownMenuView(context);
 menu.setImageRes(imageRes);
 menu.setMenuText(texts);
 // menu.setLocation(Gravity.BOTTOM | Gravity.CENTER);
 menu.setAnimStyle(R.style.pulldown_in_out);
 menu.setBackground(R.drawable.navigation_bg);
 
 return menu;
 }
}

既然是使用PopupWindow实现我们的效果,当然了,它也可以以向上弹出的方式展现。在我这个示例中,需要它展现的位置是在顶部横条下面展现,所以设置:

menu.setAnchorView(anchorView);

另外,在MainActivity中需要设置它的显示高度,在这里高度需要在顶部横条和底部RadioGroup之间,这就需要我们获取手机屏幕的高度减去顶部横条的高度,再减去底部RadioGroup的高度,最后减去手机菜单栏的高度。在点击某项菜单后,还需要将顶部中间文字和右边三角图片进行相应的变换。代码如下所示:

package com.navigation.acitvity;

import com.navigation.constant.ConstantCategoryMenu;
import com.navigation.control.PulldownMenuView;
import com.navigation.control.PulldownMenuView.OnMenuItemClickListener;
import com.navigation.utility.DeviceUtility;
import com.navigation.utility.MenuUtility;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * Android实现下拉导航选择菜单效果
 * @Description: Android实现下拉导航选择菜单效果

 * @File: MainActivity.java

 * @Package com.navigation.acitvity

 * @Author Hanyonglu

 * @Date 2012-7-28 下午06:08:27

 * @Version V1.0
 */
public class MainActivity extends Activity {
 // 今日头条LinearLayout
 private LinearLayout linearLayoutTopic = null;
 // 界面布局
 private RelativeLayout layoutHeader = null;
 private LinearLayout layoutBottom = null;
 private FrameLayout layoutBody = null;
 // PulldownMenuView基本操作类
 private MenuUtility menuUtility = null;
 // PulldownMenuView对象
 private PulldownMenuView pullDownMenu = null;
 private TextView tvTopic = null;
 private ImageView ivTopic = null;
 
 private int height = 0;
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 
 // 初始化
 initViews();
 }
 
 /**
 * 初始化
 */
 protected void initViews(){ 
 ivTopic = (ImageView) findViewById(R.id.imageViewTopic);
 tvTopic = (TextView) findViewById(R.id.textViewTopic);
 
 linearLayoutTopic = (LinearLayout)findViewById(R.id.linearLayoutTopic);
 linearLayoutTopic.setOnClickListener(TopicOnClickListener);
 layoutHeader = (RelativeLayout) findViewById(R.id.layout_top_header);
 layoutBottom = (LinearLayout) findViewById(R.id.layout_bottom);
 layoutBody = (FrameLayout) findViewById(R.id.layout_body);
 
 height = DeviceUtility.getScreenSize(this)[1] - 
 layoutHeader.getLayoutParams().height - 
 layoutBottom.getLayoutParams().height -
 DeviceUtility.getStatusBarHeight(this);
 
 menuUtility = new MenuUtility(
 MainActivity.this, 
 ConstantCategoryMenu.newsImageRes,
 ConstantCategoryMenu.newsMenuTexts,
 height,layoutHeader);
 }
 
 /**
 * 显示PulldownMenuView
 */
 protected void showPulldownMenu(){
 pullDownMenu = menuUtility.getPulldownMenuView((String)tvTopic.getText());
 ivTopic.setImageResource(R.drawable.ic_menu_trangle_up);
 }
 
 /**
 * 隐藏PulldownMenuView
 */
 protected void hidePulldownMenu(){
 pullDownMenu.releasePopupMenuView();
 ivTopic.setImageResource(R.drawable.ic_menu_trangle_down);
 }
 
 // 顶部今日头条事件监听器
 private OnClickListener TopicOnClickListener= new OnClickListener() {
 @Override
 public void onClick(View v) {
 // 开始显示下拉菜单
 showPulldownMenu();
 
 // TODO Auto-generated method stub
 pullDownMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
 @Override
 public void onMenuItemClick(AdapterView<&#63;> parent, View view, int position) {
 // TODO Auto-generated method stub
 tvTopic.setText(ConstantCategoryMenu.newsMenuTexts[position]);
 layoutBody.setBackgroundResource(ConstantCategoryMenu.newsBodyRes[position]);
 }
 
 @Override
 public void hideMenu() {
 // TODO Auto-generated method stub
 hidePulldownMenu();
 }
 });
 
 pullDownMenu.show();
 }
 };
}

我们在获取MainActivity中顶部横条和底部RadioGroup的高度时需要注意在布局文件中设置其相应的layout_height,否则,我们是获取不到其高度的。程序中间的主体部分是截取了几张图片,这个大家可以根据自己的需要设置成自己的数据格式。这点知道就可以了。

以上便是Android中实现下拉导航选择菜单效果的实现过程,是在PopupWindow中嵌入GridView实现,当然也可以在PopupWindow中嵌入ListView等各种控件实现相应的效果,也可以对PopupWindow实现各种和样的变幻效果,具体过程这里就不再详述了,有兴趣的朋友我们可以一起探讨。

源码下载:下拉导航选择菜单

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


推荐阅读
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • Python字典推导式及循环列表生成字典方法
    本文介绍了Python中使用字典推导式和循环列表生成字典的方法,包括通过循环列表生成相应的字典,并给出了执行结果。详细讲解了代码实现过程。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
author-avatar
dx152
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有