36. 【Android教程】侧滑菜单:DrawerLayout

news2024/12/30 0:44:46

侧滑菜单是用来在页面上增加一个抽屉式菜单栏的控件,它一般位于左侧,用户可以通过侧滑拉出或者关闭。通常你可以放置一些菜单项或者上下文相关的设置在里面,帮助你节省屏幕空间同时可以很方便的随时打开。侧滑菜单其实就是下面这货:

DrawerLayout

1. 侧滑菜单的特性

侧滑菜单在 Andriod 应用中非常常见,但是当你想探究实现方法的时候会发现很多早期教程都会教你使用第三方库,或者手把手教你通过一个 ListView 配合手势加上动画来实现。好消息是现在官方已经推出了一个专门用于侧滑的控件——DrawerLayout。
DrawerLayout 作为页面内容的顶层容器,让用户通过侧滑手势从屏幕边缘拉出。我们可以给它的子 View 设置layout_gravity属性来决定抽屉是从左侧或者右侧打开。

2. DrawerLayout 使用方法

DrawerLayout 作为官方提供的控件,使用起来还是很简单的,如果查看 DrawerLayout 的源码,可以发现 DrawerLayout 是直接继承至 ViewGroup 写的,所以在它内部可以承载其他的 View 同时还会有一些附属的功能。我们通常将 DrawerLayout 用做根View,然后将首页要展示的内容放在 DrawerLayout 的最前面作为第一个子 View,并且高度、宽度设置为match_parent

2.1 DrawerLayout 的常用属性

DrawerLayout 的特有属性非常少,常用的基本上就是在前文提到过的一个:layout_gravity,它的作用是指定侧滑菜单的滑动方向,常用的有以下两个值:

  • start: 从左侧划出的菜单
  • end: 从右侧划出的菜单
    该属性是作用在 DrawerLayout 的子 View 之上的,设置了layout_gravity属性的子 View 将作为一个侧滑菜单使用。

2.2 DrawerLayout 的常用 API

常用 API 只有一个,用来监听策划菜单的滑动事件:

public void addDrawerListener(DrawerListener listener) 

接口中有以下几个方法:

  • public void onDrawerSlide(View drawerView, float slideOffset)
    当侧滑菜单滑动过程中调用,传入滑动的 View 对象及滑动的距离
  • public void onDrawerOpened(View drawerView)
    当侧滑菜单打开的时候调用
  • public void onDrawerClosed(@NonNull View drawerView)
    当侧滑菜单关闭的时候调用
  • public void onDrawerStateChanged(int newState)
    当侧滑菜单滑动状态变化时调用

整体而言,官方已经为我们封装的非常好了,所以使用也比较简单,只需要掌握这几个属性和 API,就可以轻松设置属于你自己的侧滑菜单了,接下来我们一起实现一个 DrawerLayout 示例。

3 DrawerLayout 的使用示例

本节我们通过 DrawerLayout 实现一个左侧的侧滑菜单,仍然借用“水果”作为案例(提醒大家注意健康)。在 DrawerLayout 中放置一个 ListView 作为侧滑菜单载体,用户通过在 ListView 上选择从而更新主页面的内容。

3.1 编写主页面布局

整体的页面布局对按照第 2 小节所讲的规则来编写,包含几个元素:主页面标题、主页面内容、侧滑菜单。布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="@string/drawer_prompt"
        android:textSize="30sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center"
            android:text="侧滑菜单" />

        <ImageView
            android:id="@+id/imageview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#FFFFFF"
        android:choiceMode="singleChoice"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="1dp" />
</androidx.drawerlayout.widget.DrawerLayout>

3.2 编写列表布局

接着就是要针对 ListView 编写一个列表样式了,学过 ListView 的同学想必都不在话下,如果对 ListView 不熟悉的可以回顾一下第 24 节的内容,这里我们新建 list_item.xml 文件,用最经典的 TextView 搭配 ImageView 的方式:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:gravity="center"
    android:orientation="horizontal"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    android:padding="10dp" >

    <ImageView
        android:id="@+id/imageViewIcon"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:paddingRight="10dp" />

    <TextView
        android:id="@+id/textViewName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:textColor="@android:color/black"
        android:textAppearance="?android:attr/textAppearanceListItemSmall" />

</LinearLayout>

3.3 编写 ListView 适配器

其实整个项目针对 DrawerLayout 的操作并不多,更多的是在实现 ListView,这也体现了 Google 大佬们经典的封装能力。有了 ListView 布局就需要添加一个 Adapter,以供将 UI 和 数据绑定到一起。

package com.emercy.myapplication;

import android.view.View;
import android.view.ViewGroup;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyAdapter extends ArrayAdapter<Model> {

    Context mContext;
    int layoutResourceId;
    Model data[];

    public MyAdapter(Context mContext, int layoutResourceId, Model[] data) {

        super(mContext, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.mContext = mContext;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View listItem = convertView;

        LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
        listItem = inflater.inflate(layoutResourceId, parent, false);

        ImageView imageViewIcon = (ImageView) listItem.findViewById(R.id.imageViewIcon);
        TextView textViewName = (TextView) listItem.findViewById(R.id.textViewName);

        Model folder = data[position];


        imageViewIcon.setImageResource(folder.icon);
        textViewName.setText(folder.name);

        return listItem;
    }
}

3.4 编写 MainActivity 主逻辑

最后就可以进入主逻辑的编写,我们需要初始化列表数据,然后通过 Adapter 与 ListView 绑定,然后监听列表的点击也就是用户的选择,再点击的时候主页面做出相应的改变即可。

package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;

public class MainActivity extends Activity {

    private ListView mDrawerList;
    private ImageView mImage;

    Model[] mItem = new Model[3];


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);
        mImage = findViewById(R.id.imageview);

        mItem[0] = new Model(R.drawable.apple, "苹果");
        mItem[1] = new Model(R.drawable.peach, "桃子");
        mItem[2] = new Model(R.drawable.watermelon, "西瓜");

        MyAdapter adapter = new MyAdapter(this, R.layout.list_item, mItem);
        mDrawerList.setAdapter(adapter);
        mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mImage.setImageResource(mItem[position].icon);
            }
        });
    }
}

最后我们编译运行,会发现整个页面只有一个“选择水果”的提示信息,不着急,侧滑菜单当然是默认隐藏的,我们通过在屏幕左侧侧滑来请它出山,最终效果如下:

4. 小结

本节介绍了官方出品的一个侧滑菜单控件,它是直接继承自 ViewGroup 实现的,通常我们会把它作为整个页面的根布局,然后将主页面作为 DrawerLayout 的第一个子 View。接着为需要侧滑的列表添加layout_gravity属性,最后按照需要添加一个监听器,就可以完成侧滑功能了。在 DrawerLayout 出来之前,有各式各样第三方的侧滑控件,大家可以翻看一些比较古老的帖子或者教程学习学习,但是使用上还是推荐使用官方 DrawerLayout 控件,在细节和封装以及后期维护上还是很具有优势的。

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

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

相关文章

python 对图片进行操作

Pillow是一个强大的图像处理库&#xff0c;它提供了许多用于打开、操作和保存图像的功能。 Image模块&#xff1a; Image模块提供了用于打开、创建、编辑和保存图像的基本功能。可以使用Image.open()函数来打开图像文件&#xff0c;或者使用Image.new()函数来创建新的图像,还可…

【Java框架】Spring框架(六)——Spring中的Bean的作用域

目录 Bean的作用域1.singleton(默认)代码示例 2.prototype代码示例 3.request代码示例 4.session代码示例 5.application代码示例 websocket Bean的作用域 Spring支持6个作用域&#xff1a;singleton、prototype、request、session、application、websocket 1.singleton(默认…

山与路远程控制 一个基于electron和golang实现的远控软件

山与路远程控制 &#x1f3a5;项目演示地址 还在制作… ♻️项目基本介绍 山与路远程控制是基于electron(vue3)和golang实现的远程控制软件(项目界面主要模仿向日葵远程软件,如有侵权请告知),代码可能有点臃肿毕竟只花了一周左右写的无聊项目,如果对其感兴趣的大佬可以fork自…

【信号处理】心电信号传统R波检测定位典型方法实现(matlab)

关于 心电信号中QRS波检测是一个非常重要的步骤&#xff0c;可以用于实现重要波群的基本定位&#xff0c;在定位基础上&#xff0c;可以进一步分析心电信号的特征变化&#xff0c;从而为医疗诊断提供必要的参考。 工具 MATLAB ECG心电信号 方法实现 ECG心电信号加载 ecg …

Java中的数组(上)

1.怎样定义Java中的数组 package day40; ​ public class day25 {public static void main(String[] args) {int[] array1{1,2,3,4,5};int[] array2new int[10];for (int i 0; i < array1.length; i) {System.out.print(array1[i]" ");}System.out.println();fo…

学习笔记:Vue2中级篇

Vue2 学习笔记&#xff1a;Vue2基础篇_ljtxy.love的博客-CSDN博客学习笔记&#xff1a;Vue2中级篇_ljtxy.love的博客-CSDN博客学习笔记&#xff1a;Vue2高级篇_ljtxy.love的博客-CSDN博客 Vue3 学习笔记&#xff1a;Vue3_ljtxy.love的博客&#xff09;-CSDN博客 文章目录 5.…

HTTP 方法和使用场景大全

本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 HTTP 方法和使用场景大全 HTTP&#xff08;超文本传输协议&#xff09;方法&#xff0c;也称为 HTTP 动词&#xff0c;定义了可以对资源执行的操作。理解这些方法的使用对于 Web 开发至…

【分治】Leetcode 排序数组

题目讲解 912. 排序数组 算法讲解 我们这里使用三指针&#xff0c;将数组分成三块&#xff1a;<key 和 key 和 >key,如果当前指针指向的数字<key&#xff0c;我们就swap(nums[left]), nums[i] 。如果当前的数字key &#xff0c;就让i。如果当前的数字>key&…

MySQL基础篇总结

参考&#xff1a;黑马程序员MySQL基础视频链接 数据库基本操作 启动与停止 1.第一种方式&#xff1a; 1>以管理员身份运行cmd 2>在命令行窗口中输入: 启动:net start mysql80停止:net stop mysql80 2.第二种方式: 1>WinR快捷方式打开如下&#xff1a; 输入&#…

【探索Linux】P.32(自定义协议)

阅读导航 引言一、自定义协议概念二、自定义协议需要注意的事项三、自定义协议示例(跨网络计算器协议)✅协议代码&#xff08;Protocol.hpp&#xff09;1. 计算器协议简单介绍2. 序列化部分3. 反序列化部分4. 请求和响应数据结构5. 使用自定义协议 四、总结温馨提示 引言 在上…

第三届 SWCTF-Web 部分 WP

写在前面 题目主要涉及的是前端 php 内容知识&#xff0c;仅以本篇博客记录自己 Web 出题的奇思妙想。 Copyright © [2024] [Myon⁶]. All rights reserved. 目录 1、HTTP 2、再见了晚星 3、myon123_easy_php 4、baby_P0P 5、LOGIN!!! 1、HTTP 首页文件默认就是 ind…

BTP连接cloud connector中配置的SAP

登录地址 登录之后可以看到我们已经配置成功的后端系统SAP。 从cloud connector中获取location ID ,然后在BTP中配置Destination 选择目标标签页&#xff0c;点击‘新建目标’&#xff0c;如下图&#xff1a; 新建连接 暂时不知道错误原因 创建目标-HTTP  新建目标&…

Leetcode 第 394 场周赛

Leetcode 第 394 场周赛 1. [统计特殊字母的数量 I](https://leetcode.cn/problems/count-the-number-of-special-characters-i/)2. [统计特殊字母的数量 II](https://leetcode.cn/problems/count-the-number-of-special-characters-ii/)3. [使矩阵满足条件的最少操作次数](htt…

大一考核题解

在本篇中&#xff0c;将尽力使用多种解法&#xff0c;来达到一题多练的效果。 1&#xff1a; 1.原题链接&#xff1a; 238. 除自身以外数组的乘积 - 力扣&#xff08;LeetCode&#xff09; 这道题首先一眼肯定想到拿整体的积除以当前元素&#xff0c;将结果作为ans&#xff0c;…

护眼台灯哪个牌子最好?盘点五款目前比较好用的护眼台灯

护眼台灯哪个牌子好&#xff1f;护眼台灯比较好的牌子有书客、雷士、爱德华医生等。这些护眼台灯得益于强大的研发实力&#xff0c;不仅具备基础的照明功能&#xff0c;更在护眼效果上表现卓越。它们能够真正起到保护眼睛的作用&#xff0c;有效缓解眼部疲劳&#xff0c;为阅读…

Unity3D 羊了个羊等游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

怎样快速打造二级分销小程序

乔拓云是一个专门开发小程序模板的平台&#xff0c;致力于帮助商家快速上线自己的小程序。通过套用乔拓云提供的精美模板&#xff0c;商家无需具备专业的技术背景&#xff0c;也能轻松打造出功能齐全、美观大方的小程序。 在乔拓云的官网&#xff0c;商家可以免费注册账号并登录…

【批量区域识别内容重命名】批量识别图片区域文字并重命名,批量图片部分识别内容重命文件,PDF区域识别提取重命名

我们在工作和生活中经常遇到这样的需求&#xff1a;比如将以下的图片区域识别进行重命名&#xff0c;批量识别后改成以时间和工作内容重命名&#xff0c;便于日后检索&#xff0c;快速查询 首先我们拍摄照片用到的是水印相机&#xff0c;这里的文字呢我们需要加个背景&#xff…

[数字人]唇形驱动,不生成头部动作算法总结

安全验证 - 知乎知乎&#xff0c;中文互联网高质量的问答社区和创作者聚集的原创内容平台&#xff0c;于 2011 年 1 月正式上线&#xff0c;以「让人们更好的分享知识、经验和见解&#xff0c;找到自己的解答」为品牌使命。知乎凭借认真、专业、友善的社区氛围、独特的产品机制…

【数据结构】时间复杂度的例题

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构 &#x1f337;追光的人&#xff0c;终会万丈光芒 前言&#xff1a; 这篇文章是关于时间复杂度的一些例题&#xff0c;关于时间复杂度和空间复杂度和算法的计算效率的基本知识点我放在…