文档章节

安卓滑动隐藏显示菜单功能实现(还有蒙板校果),只显示一半view

D
 Duke__
发布于 2014/03/04 21:29
字数 1429
阅读 2173
收藏 2

好吧.我是标题党.其实我说的显示一半的不是activity. 而是看上去像只显示一半activity.

但真实的是只是操作其中一个view

网上有很多这类的代码. 但怎么都不及自己写的自己理解的深刻.

这文章给你带来的只是引导作用.希望可以帮到像我当初一样疑惑的人

首先说页理

我的想法是这样的: 两个帧布局. 一上一下. 点击一下按扭. 上面那个往右显. 让下面的那个露出一部份来

所有的关键是操作上面那个布局的Leftmargin. 然后再开线程来一点点改变Leftmargin的值.让上面布局滑动起来

很简单吧..初当可把我想得纠结死了.网上的案例都很复杂

如果做过web前端的人应很易理解 . 因为在div+css只会大量应用到这个Leftmargin

里面有大量的注释...不知道能不能看懂.写得有点乱.当时很困了

上草图

现\

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    
    <include layout="@layout/frame_leftmenu"/>
	
	<include layout="@layout/frame_middlecontent"/>
    
</FrameLayout>


底局layout我的叫fram_leftmenu. 上层的我的叫frame_middlecontent

fram_leftmenu.xml

<?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="match_parent"
    android:visibility="gone"
    android:id="@+id/leftmenu_layout"
    android:background="#0000cc" >
    
</LinearLayout>


frame_middlecontent.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:id="@+id/midcontent_layout" >
    
    <LinearLayout 
        android:id="@+id/middlecontent_first"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView 
            android:id="@+id/leftmenu_btn_img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/ic_launcher"/>
    </LinearLayout>
    <LinearLayout 
        android:id="@+id/middlecontent_second"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#e0000000"
        android:visibility="gone">
    </LinearLayout>
</FrameLayout>


这里是Mainactivtiy.java

package com.hai.goleftright;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity implements OnTouchListener{
	/**左边菜单*/
	LinearLayout leftLayout;
	/**右边菜单*/
	//LinearLayout rightLayout;
	/**蒙板--当middleLayout移动后.该蒙板覆盖middleLayout*/
	LinearLayout middlecontent_second;
	/**中间内容*/
	FrameLayout midLayout;
	/**用于展开左边菜单的按扭*/
	ImageView imageView;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        leftLayout = (LinearLayout) findViewById(R.id.leftmenu_layout);
        //rightLayout = (LinearLayout) findViewById(R.id.rightmenu_layout);
        midLayout = (FrameLayout) findViewById(R.id.midcontent_layout);
        
        imageView = (ImageView) findViewById(R.id.leftmenu_btn_img);
        middlecontent_second = (LinearLayout) findViewById(R.id.middlecontent_second);
        imageView.setOnTouchListener(this);
        middlecontent_second.setOnTouchListener(this);
    }
    
	public boolean onTouch(View v, MotionEvent event) {
		MinLayoutAsyncTask asyncTask = null;
		switch (v.getId()) {
		case R.id.leftmenu_btn_img:
			//设置左边菜单为显状态
			leftLayout.setVisibility(View.VISIBLE);
			//设置蒙版为显示状态
			middlecontent_second.setVisibility(View.VISIBLE);
			//设置蒙板的透明度
			middlecontent_second.getBackground().setAlpha(50);
			//实例化滑动任务 参数1: 要滑动的layout, 参数2: 最终滑动距离, 参数3: 移动方向
			asyncTask = new MinLayoutAsyncTask(midLayout, 200,"right");
			//开始任务 参数: 每次滑动的距离
			asyncTask.execute(10); 
			break;
		case R.id.middlecontent_second:
			asyncTask = new MinLayoutAsyncTask(leftLayout,midLayout, 0,"left");
			asyncTask.execute(-10);
			middlecontent_second.setVisibility(View.GONE);
			break;
		}
		return true; 
	}
}


线程更新主UI..可以用 Runnable+ handle的方式, 子线程每更新一次Leftmargin的值就通知主线程更新一下UI. 

只要线程沉睡时间与Leftmargin的值控制得好.便可得动画滑动效果

我为了结构方便,书写简单. 用的是AsyncTast这个类来实现异步任务

下面这个数就作用就是不停地更新主UI.

MinLayoutAsyncTask.java

package com.hai.goleftright;

import android.os.AsyncTask;
import android.view.View;
import android.widget.FrameLayout;

public class MinLayoutAsyncTask extends AsyncTask<Integer, Integer, Integer> {
	private static final String RIGHT = "right";
	private static final String LEFT = "left";
	/**要显示的底部rightLayout*/
	View underLayout;
	/**要控制移动的layout*/
	FrameLayout midLayout;
	/**layout的参数对象*/
	FrameLayout.LayoutParams midLayoutParams;
	/**最终距离*/
	int max;
	/**移动方向*/
	String direction;
	/**
	 * 构造器
	 * @param midLayout 要控制的layout
	 * @param speed 每秒的移动距离
	 * @param max 最终要达到的距离
	 * @param 移动方向 "right"/"left"
	 */
	public MinLayoutAsyncTask(View underLayout,View midLayout,int max,String direction){
		this.underLayout = underLayout;
		this.midLayout = (FrameLayout) midLayout;
		this.max = max;
		this.direction = direction;
		
	}
	public MinLayoutAsyncTask(View midLayout,int max,String direction){
		this(null,midLayout,max,direction);
	}
	
	/**
	 * 任务开始前的准备工作
	 */
	@Override
	protected void onPreExecute() {
		midLayoutParams = (FrameLayout.LayoutParams) midLayout.getLayoutParams();
	}
	
	/**
	 * @param speed 该类实例.execute(int i) 传进来的参数  每次移动的距离
	 */
	@Override
	protected Integer doInBackground(Integer... speed) {
		/**每次进来都先获取layout的现时leftMargin*/
		int leftMargin = midLayoutParams.leftMargin;
		
		// 根据传入的速度来滚动界面,当滚动到达最大距离时,跳出循环
		while(true){
			//当前leftMargin加要移动的距离*
			leftMargin = leftMargin + speed[0];
			//移动方向
			if(RIGHT.equals(direction)){
				if(leftMargin > max){
					leftMargin = max;
					break;
				}
			}
			if(LEFT.equals(direction)){
				if(leftMargin < max){
					leftMargin = max;
					break;
				}
			}
			sleep(10);
			publishProgress(leftMargin);
		}
		
		return leftMargin;
	}
	
	@Override
	protected void onProgressUpdate(Integer... leftMargin) {
		midLayoutParams.leftMargin = leftMargin[0];
		midLayout.setLayoutParams(midLayoutParams);
	}
	
	/**
	 * 完成任务后在UI主线程执行的方法 参数是doInBackground返回的结果
	 */
	@Override
	protected void onPostExecute(Integer leftMargin) {
		if(leftMargin == 0){
			underLayout.setVisibility(View.GONE);
		}
		midLayoutParams.leftMargin = leftMargin;
		midLayout.setLayoutParams(midLayoutParams);
	}
	
	private void sleep(int min){
		try {
			Thread.sleep(min);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}


到这里就写完了.

其实代码有点多.但关键理解原理就行了

再一次总结原理

利用帧布局实面一上一下两个Layout. 点击按钮(或你可以实现划动事件.我没写完)把上层layout往右推过一点

把下层layout显示出来. 关键是控制Leftmargin的值. 然后就是线程更新UI的问题了


其实这里我觉得还有很多多余的代码

因为我为了实现. "当上层Layout右移之后. 它的所有组件的点击事件都要失效" 这个想法...

我给上层Layout加上了一层蒙板..这样上层layout右移之后. 我只要用蒙板去拦截事件就可以了

这里应该有更好的办法.但目前我还没想到...有好建议的朋友希望补充.


注: 部份优秀代码来自于网络,本文总结修改完善

© 著作权归作者所有

D
粉丝 0
博文 2
码字总数 3704
作品 0
广州
私信 提问
android中ViewPager详解--视图滑动、界面卡等效果 (一)

这是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api。而viewpager就是其中之一。利用它,我们可以做很多事情,从最简单的导航,到页面菜单...

一别经年
2014/01/21
0
0
与Status Bar和Navigation Bar相关的一些东西

与StatusBar和NavigationBar相关的东西有两种,一是控制它们的显示与隐藏,二是控制它们的透明与否及背景。 在2.3及以前,StatusBar只能显示与隐藏,即全屏模式,通过WindowManager.LayoutP...

Jerikc
2015/08/20
0
0
Android7.0 分屏下 Activity 与 Fragment 生命周期(一)

小菜前段时间整理了一篇关于我们真的了解 Activity 与 Fragment 的生命周期吗?的小博文,整理了基础版的关于 Activity 与 Fragment 的生命周期。 后来又一次被一个大大神问到在 Android7.0...

阿策神奇
2018/06/11
0
0
开源中国 OsChina Android 客户端源码分析(2)滑动菜单DrawerLayout

1滑动菜单oschina使用了android.support.v4.widget.DrawerLayout,之前没有用过这个控件,百度了下,大致了解如下: 1.1类似与LinearLayout,就是一个布局控件。 1.2使用时,其有两部分组成,...

姬鑫
2015/05/20
0
3
Android ActionBar详解

关于ActionBar,相信大家并不陌生,但是真正能够熟练使用的也不是很多,这篇文章主要为大家详细介绍ActionBar的相关知识,ActionBar是在Android3.0中引入的概念,所以在2.x系统中使用ActionBar...

恰同学少年
2015/08/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周二乱弹 —— 吾不好梦中插人

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @鱼豆腐233 :#今日歌曲分享# 分享My Chemical Romance的单曲《I Don't Love You》: 《I Don't Love You》- My Chemical Romance 手机党少年们...

小小编辑
46分钟前
17
4
ss5 vpn 安装(linux版本)

1. 创建一个文件夹 /ss5 你也可以自定义,不过后续的地方需要注意自己的地址 2. 下载ss5文件(如果你的服务器没有安装wget请使用 yum -y install wget 命令安装 如果连yum都没安装自己查去)(下...

太黑_thj
今天
2
0
八、RabbitMQ的集群原理

集群架构 写在前面 RabbitMQ集群是按照低延迟环境设计的,千万不要跨越WAN或者互联网来搭建RabbitMQ集群。如果一定要在高延迟环境下使用RabbitMQ集群,可以参考使用Shovel和Federation工具。...

XuePeng77
今天
5
0
mac系统下,brew 安装mysql,用终端可以连接,navicat却连接不上?

问题: 1.报错? 2059 - Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(../Frameworks/caching_sha2_password.so, 2): image not found 2.自己通过设置,已经把密......

写bug的攻城狮
昨天
3
0
老生常谈,HashMap的死循环

问题 最近的几次面试中,我都问了是否了解HashMap在并发使用时可能发生死循环,导致cpu100%,结果让我很意外,都表示不知道有这样的问题,让我意外的是面试者的工作年限都不短。 由于HashMap...

群星纪元
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部