您的位置:首页 > 其它

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

2016-10-29 20:19 441 查看
摘要: 首先说页理 我的想法是这样的: 两个帧布局. 一上一下. 点击一下按扭. 上面那个往右显. 让下面的那个露出一部份来 所有的关键是操作上面那个布局的Leftmargin. 然后再开线程来一点点改变Leftmargin的值.让上面布局滑动起来

好吧.我是标题党.其实我说的显示一半的不是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右移之后. 我只要用蒙板去拦截事件就可以了
这里应该有更好的办法.但目前我还没想到...有好建议的朋友希望补充.

注: 部份优秀代码来自于网络,本文总结修改完善
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  只显示一半view
相关文章推荐