android左侧菜单栏实现

本文介绍如何在Android中实现一个左侧滑动菜单。通过自定义控件`MySlideView`,结合布局文件和代码实现菜单栏的显示、滑动效果。在`MainActivity`中设置手势监听,根据滑动速度和位置动态调整菜单栏的显示状态。

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

 

首先上图,左边为菜单栏显示的样式,右边为滑动过程的样式,滑动结束后应该是菜单栏完全影藏

 

上代码

布局文件:

1、activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/slideView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <com.example.myslideview.MySlideView
        android:id="@+id/myView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </com.example.myslideview.MySlideView>

</LinearLayout>

2、slide_view.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <LinearLayout
        android:id="@+id/slideView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" >
    </LinearLayout>

</LinearLayout>

3、view1.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingTop="5dp" >

    <ListView
        android:id="@+id/lstView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</LinearLayout>

4、view2.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/content" />

</LinearLayout>

 

代码文件

1、MySlideView.java

package com.example.myslideview;

import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;

public class MySlideView extends LinearLayout {
 LinearLayout mLinout;
 View view1, view2;// 两个子空间,view1为菜单页,view2为内容页
 int v1MaLfMin;// 当前view1的偏移量
 int MARGINLEFTMAX;// 移动到最左边是view1的偏移量

 public MySlideView(Context context) {
  super(context);
 }

 public MySlideView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // 读取控件的基础布局
  LayoutInflater.from(context).inflate(R.layout.slide_view, this);
  mLinout = (LinearLayout) findViewById(R.id.slideView);
 }

 public void addView(View view, LayoutParams params) {
  // 想控件中添加子控件
  if (params != null) {
   mLinout.addView(view, params);
  } else {
   mLinout.addView(view);
  }
 }

 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
  if (changed) {
   // 设置两个子控件的显示位置,默认显示内容页,即菜单页想向左偏移自身的宽度
   view1 = mLinout.getChildAt(0);
   view2 = mLinout.getChildAt(1);
   MarginLayoutParams leftMargin = (MarginLayoutParams) view1
     .getLayoutParams();
   leftMargin.leftMargin = 0 - leftMargin.width;
   v1MaLfMin = 0 - leftMargin.width;
   MARGINLEFTMAX = v1MaLfMin;
   view1.setLayoutParams(leftMargin);
  }
  super.onLayout(changed, l, t, r, b);
 }

 public void showView(float f) {
  //根据当前手指的滑动距离动态改变菜单页的偏移量
  MarginLayoutParams leftMargin = (MarginLayoutParams) view1
    .getLayoutParams();
  if (f != 0) {
   int index = (int) (v1MaLfMin + f);
   if (index >= MARGINLEFTMAX && index <= 0) {
    leftMargin.leftMargin = index;
    view1.setLayoutParams(leftMargin);
   }
  }
 }

 public void showTo(float f) {
  //f大于0滑向右边
  //否则滑向左边
  MarginLayoutParams leftMargin = (MarginLayoutParams) view1
    .getLayoutParams();
  if (f > 0) {
   // 滑到最右边
   (new ScorllScreenTask(1)).execute();
  } else {
   // 滑到最左边
   (new ScorllScreenTask(-1)).execute();
  }
 }

 public void showJudge() {
  //手指离开屏幕的时候根据当前偏移量,
  //如果当前偏移量大于二分之一,滑动到右侧
  //如果当前偏移量小于二分之一,滑动到左侧
  MarginLayoutParams leftMargin = (MarginLayoutParams) view1
    .getLayoutParams();
  if (leftMargin.leftMargin > MARGINLEFTMAX / 2) {
   showTo(1);
  } else {
   showTo(-1);
  }
 }
 /**
  * 滑动事件做成一个任务
  * 滑动过程中按照一个固定的速度改变偏移量
  * 每个一段时间是的线程睡眠一段时间
  * 使得滑动时间看起来比较平滑
  */
 class ScorllScreenTask extends AsyncTask<Void, Integer, Void> {
  int left_right;//判断左滑还是右滑大于零右滑小于零左滑
  boolean stop_flag = false;//滑动时间停止标记
  int speed;//滑动速率

  public ScorllScreenTask(int i) {
   //右滑速率为30,左滑速率为-30
   left_right = i;
   if (left_right > 0) {
    speed = 30;
   } else {
    speed = -30;
   }
  }

  @Override
  protected void onPostExecute(Void result) {
   int lastMargin = 0;
   //动画结束后的最终位置
   if (left_right > 0) {
    lastMargin = 0;
    v1MaLfMin = 0;
   } else {
    lastMargin = MARGINLEFTMAX;
    v1MaLfMin = MARGINLEFTMAX;
   }
   MarginLayoutParams leftMargin = (MarginLayoutParams) view1
     .getLayoutParams();
   leftMargin.leftMargin = lastMargin;
   view1.setLayoutParams(leftMargin);
   super.onPostExecute(result);
  }

  @Override
  protected void onProgressUpdate(Integer... values) {
   //动画执行过程中实时更行滑动的位置
   MarginLayoutParams leftMargin = (MarginLayoutParams) view1
     .getLayoutParams();
   leftMargin.leftMargin = values[0];
   view1.setLayoutParams(leftMargin);
   super.onProgressUpdate(values);
  }

  @Override
  protected Void doInBackground(Void... params) {
   while (!stop_flag) {
    //每隔25毫秒滑动一个速度
    MarginLayoutParams leftMargin = (MarginLayoutParams) view1
      .getLayoutParams();
    int left = leftMargin.leftMargin;
    if (left + speed > MARGINLEFTMAX && left + speed < 0) {
     publishProgress(left + speed);
     try {
      Thread.sleep(25);
     } catch (Exception e) {
      e.printStackTrace();
     }
    } else {
     stop_flag = true;
    }
   }
   return null;
  }
 }

}

 

2、MainActivity.java

 

package com.example.myslideview;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.Handler;
import android.R.integer;
import android.app.Activity;
import android.text.BoringLayout.Metrics;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.LinearLayout.LayoutParams;

public class MainActivity extends Activity {
 // 自定义控件
 MySlideView mSlideView;
 // view1为菜单页,view2为内容页
 View view1, view2;
 DisplayMetrics dm = new DisplayMetrics();
 Handler myHandler = new Handler();
 float xDown;// 记录手指按下瞬间的x坐标
 float xUp;// 记录手指松开瞬间的x坐标
 float xNow;// 记录手指滑动时刻的x坐标
 VelocityTracker mVelocityTracker;// 获取手指滑动速率控件
 ListView mListView;// 菜单页中的listview

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  initView();
 }

 private void initView() {
  // 初始化
  mSlideView = (MySlideView) findViewById(R.id.myView);
  view1 = getLayoutInflater().inflate(R.layout.view1, null);
  mListView = (ListView) view1.findViewById(R.id.lstView1);
  setArrayAdapter();
  view2 = getLayoutInflater().inflate(R.layout.view2, null);
  LayoutParams params1, params2;
  getWindowManager().getDefaultDisplay().getMetrics(dm);
  // 设置菜单页的宽度为屏幕宽度的四分之三
  params1 = new LayoutParams(dm.widthPixels * 3 / 4, dm.heightPixels);
  params2 = new LayoutParams(dm.widthPixels, dm.heightPixels);
  mSlideView.addView(view1, params1);
  mSlideView.addView(view2, params2);
 }

 private void setArrayAdapter() {
  final List<String> arrs = new ArrayList<String>();
  arrs.add("消息");
  arrs.add("聊天");
  arrs.add("找人");
  arrs.add("附近");
  arrs.add("新鲜事");
  arrs.add("公共主页");
  arrs.add("微博广角");
  arrs.add("新闻事件");
  arrs.add("关注");
  arrs.add("设置");
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_list_item_single_choice, arrs);
  mListView.setAdapter(adapter);
  mListView.setOnItemClickListener(new OnItemClickListener() {

   @Override
   public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
     long arg3) {
    Toast.makeText(MainActivity.this, arrs.get(arg2),
      Toast.LENGTH_SHORT).show();
   }
  });
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 public void showLogLXL(String lxl) {
  Log.e("LXL", lxl);
 }

 // 根据手指滑动时间控制控件的移动
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  if (mVelocityTracker == null) {
   // 速率控件初始化
   mVelocityTracker = VelocityTracker.obtain();
  }
  // 计算没500毫毛的速率
  mVelocityTracker.addMovement(event);
  mVelocityTracker.computeCurrentVelocity(500);
  float speed = mVelocityTracker.getXVelocity();
  if (event.getAction() == MotionEvent.ACTION_MOVE) {
   // 手指在屏幕上滑动的时候控制控件向滑动的方向移动
   xNow = event.getX();
   mSlideView.showView(xNow - xDown);
  } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
   // 记录手指按下的时刻的x坐标
   xDown = event.getX();
  } else if (event.getAction() == MotionEvent.ACTION_UP) {
   if (speed > 1500) {
    // 向右滑动的速录大于1500时直接滑动到右侧
    mSlideView.showTo(1);
    return false;
   } else if (speed < -1500) {
    // 向左滑动的速度大于1500时直接滑动到左边
    mSlideView.showTo(-1);
    return false;
   }
   // 当滑动速率没有超过1500时,在手指松开的时刻根据当前的x坐标判断,
   // 如果x坐标大于二分之一则滑到右边否则滑到左边,
   // 不管则样不能让控件停在中间,要么滑到左边要么滑到右边
   xUp = event.getX();
   mSlideView.showJudge();
   return false;
  }
  return super.onTouchEvent(event);
 }
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值