android自定义右菜单,Android侧边栏的自定义实现

本文介绍如何实现Android应用中通过滑动手势显示和隐藏自定义的右侧菜单。通过监听触摸事件,计算滑动速度和距离,动态调整菜单栏的位置,实现了平滑的动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文要实现手指在手机上向左或向右移动时,能相应的移动左右两个视图

先来看看效果:

A133452614-129905.png_small.png

一、实现思路

1.思路

菜单在左,内容在右,然后菜单显示时和手机右边框有一定的间隔,内容显示一小部分。内容全部显示时,菜单全部不可见。如下面两个图A133455005-129905.png_small.png

显示内容

A133457161-129905.png_small.png

显示菜单

2.判断逻辑

这是判断手指按着屏幕和手指抬起时要不要显示还是隐藏菜单

A133459333-129905.png_small.png

二、代码清单

首先来看下布局:

android:id="@+id/layout"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal"

tools:context=".MainActivity" >

android:id="@+id/menu"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal"

android:background="@drawable/pn" >

android:id="@+id/content"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal"

android:background="@drawable/sn">

接下来看看代码

package com.example.learningjava;

import com.example.learningjava.R.string;

import android.R.integer;

import android.R.menu;

import android.os.AsyncTask;

import android.os.Build;

import android.os.Bundle;

import android.annotation.SuppressLint;

import android.annotation.TargetApi;

import android.widget.LinearLayout.LayoutParams;

import android.app.Activity;

import android.util.DisplayMetrics;

import android.util.Log;

import android.view.Menu;

import android.view.MotionEvent;

import android.view.VelocityTracker;

import android.view.View;

import android.view.View.OnTouchListener;

import android.view.Window;

import android.widget.LinearLayout;

public class MainActivity extends Activity implements OnTouchListener{

private LinearLayout menuLayout;//菜单项

private LinearLayout contentLayout;//内容项

private LayoutParams menuParams;//菜单项目的参数

private LayoutParams contentParams;//内容项目的参数contentLayout的宽度值

private int disPlayWidth;//手机屏幕分辨率

private float xDown;//手指点下去的横坐标

private float xMove;//手指移动的横坐标

private float xUp;//记录手指上抬后的横坐标

private VelocityTracker mVelocityTracker; // 用于计算手指滑动的速度。

float velocityX;//手指左右移动的速度

public static final int SNAP_VELOCITY = 400; //滚动显示和隐藏menu时,手指滑动需要达到的速度。

private boolean menuIsShow = false;//初始化菜单项不可翙

private static final int menuPadding=80;//menu完成显示,留给content的宽度

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.activity_main);

initLayoutParams();

}

/**

*初始化Layout并设置其相应的参数

*/

private void initLayoutParams()

{

//得到屏幕的大小

DisplayMetrics dm = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(dm);

disPlayWidth =dm.widthPixels;

//获得控件

menuLayout = (LinearLayout) findViewById(R.id.menu);

contentLayout = (LinearLayout) findViewById(R.id.content);

findViewById(R.id.layout).setOnTouchListener(this);

//获得控件参数

menuParams=(LinearLayout.LayoutParams)menuLayout.getLayoutParams();

contentParams = (LinearLayout.LayoutParams) contentLayout.getLayoutParams();

//初始化菜单和内容的宽和边距

menuParams.width = disPlayWidth - menuPadding;

menuParams.leftMargin = 0 - menuParams.width;

contentParams.width = disPlayWidth;

contentParams.leftMargin=0;

//设置参数

menuLayout.setLayoutParams(menuParams);

contentLayout.setLayoutParams(contentParams);

}

@Override

public boolean onTouch(View v, MotionEvent event)

{

acquireVelocityTracker(event);

switch (event.getAction())

{

case MotionEvent.ACTION_DOWN:

xDown=event.getRawX();

break;

case MotionEvent.ACTION_MOVE:

xMove=event.getRawX();

isScrollToShowMenu();

break;

case MotionEvent.ACTION_UP:

xUp=event.getRawX();

isShowMenu();

releaseVelocityTracker();

break;

case MotionEvent.ACTION_CANCEL:

releaseVelocityTracker();

break;

}

return true;

}

/**

* 根据手指按下的距离,判断是否滚动显示菜单

*/

private void isScrollToShowMenu()

{

int distanceX = (int) (xMove - xDown);

if (!menuIsShow) {

scrollToShowMenu(distanceX);

}else{

scrollToHideMenu(distanceX);

}

}

/**

* 手指抬起之后判断是否要显示菜单

*/

private void isShowMenu()

{

velocityX =getScrollVelocity();

if(wantToShowMenu()){

if(shouldShowMenu()){

showMenu();

}else{

hideMenu();

}

}

else if(wantToHideMenu()){

if(shouldHideMenu()){

hideMenu();

}else{

showMenu();

}

}

}

/**

*想要显示菜单,当向右移动距离大于0并且菜单不可见

*/

private boolean wantToShowMenu(){

return !menuIsShow&&xUp-xDown>0;

}

/**

*想要隐藏菜单,当向左移动距离大于0并且菜单可见

*/

private boolean wantToHideMenu(){

return menuIsShow&&xDown-xUp>0;

}

/**

*判断应该显示菜单,当向右移动的距离超过菜单的一半或者速度超过给定值

*/

private boolean shouldShowMenu(){

return xUp-xDown>menuParams.width/2||velocityX>SNAP_VELOCITY;

}

/**

*判断应该隐藏菜单,当向左移动的距离超过菜单的一半或者速度超过给定值

*/

private boolean shouldHideMenu(){

return xDown-xUp>menuParams.width/2||velocityX>SNAP_VELOCITY;

}

/**

* 显示菜单栏

*/

private void showMenu()

{

new showMenuAsyncTask().execute(50);

menuIsShow=true;

}

/**

* 隐藏菜单栏

*/

private void hideMenu()

{

new showMenuAsyncTask().execute(-50);

menuIsShow=false;

}

/**

*指针按着时,滚动将菜单慢慢显示出来

*@param scrollX 每次滚动移动的距离

*/

private void scrollToShowMenu(int scrollX)

{

if(scrollX>0&&scrollX<= menuParams.width)

menuParams.leftMargin =-menuParams.width+scrollX;

menuLayout.setLayoutParams(menuParams);

}

/**

*指针按着时,滚动将菜单慢慢隐藏出来

*@param scrollX 每次滚动移动的距离

*/

private void scrollToHideMenu(int scrollX)

{

if(scrollX>=-menuParams.width&&scrollX<0)

menuParams.leftMargin=scrollX;

menuLayout.setLayoutParams(menuParams);

}

/**

* 创建VelocityTracker对象,并将触摸content界面的滑动事件加入到VelocityTracker当中。

* @param event 向VelocityTracker添加MotionEvent

*/

private void acquireVelocityTracker(final MotionEvent event) {

if(null == mVelocityTracker) {

mVelocityTracker = VelocityTracker.obtain();

}

mVelocityTracker.addMovement(event);

}

/**

* 获取手指在content界面滑动的速度。

* @return 滑动速度,以每秒钟移动了多少像素值为单位。

*/

private int getScrollVelocity() {

puteCurrentVelocity(1000);

int velocity = (int) mVelocityTracker.getXVelocity();

return Math.abs(velocity);

}

/**

* 释放VelocityTracker

*/

private void releaseVelocityTracker() {

if(null != mVelocityTracker) {

mVelocityTracker.clear();

mVelocityTracker.recycle();

mVelocityTracker = null;

}

}

/**

*

*:模拟动画过程,让肉眼能看到滚动的效果

*

*/

class showMenuAsyncTask extends AsyncTask

{

@Override

protected Integer doInBackground(Integer... params)

{

int leftMargin = menuParams.leftMargin;

while (true)

{// 根据传入的速度来滚动界面,当滚动到达左边界或右边界时,跳出循环。

leftMargin += params[0];

if (params[0] > 0 && leftMargin > 0)

{

leftMargin= 0;

break;

} else if (params[0] < 0 && leftMargin

{

leftMargin=-menuParams.width;

break;

}

publishProgress(leftMargin);

try

{

Thread.sleep(40);//休眠一下,肉眼才能看到滚动效果

} catch (InterruptedException e)

{

e.printStackTrace();

}

}

return leftMargin;

}

@Override

protected void onProgressUpdate(Integer... value)

{

menuParams.leftMargin = value[0];

menuLayout.setLayoutParams(menuParams);

}

@Override

protected void onPostExecute(Integer result)

{

menuParams.leftMargin = result;

menuLayout.setLayoutParams(menuParams);

}

}

}

三、效果与说明

A133501864-129905.png_small.png

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值