Android 自定义抽屉

自定义抽屉

1丶继承自  FrameLayout  原因是可以多层镶嵌

2丶用正余弦定理根据手势滑动来判断抽屉的开关

MainActivity

package com.example.zidingyict;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;


public class MainActivity extends Activity {
private LeftSlidingMenu leftSlidingMenu;
private List<String>list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initList();
        initView();
    }
private void initList() {
// TODO Auto-generated method stub
list=new ArrayList<String>();
for (int i = 0; i < 30; i++) {
list.add("item"+i);
}
}
private void initView() {
// TODO Auto-generated method stub
leftSlidingMenu=(LeftSlidingMenu)findViewById(R.id.myslidingMenu);
ImageView imageView=new ImageView(this);
imageView.setImageResource(R.drawable.ic_launcher);
imageView.setScaleType(ScaleType.FIT_XY);
leftSlidingMenu.setBottomView(imageView);
ListView listView = new ListView(this);
ArrayAdapter<String>adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(adapter);
leftSlidingMenu.setTopView(listView);
}
}

LeftSlidingMenu

package com.example.zidingyict;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.FrameLayout.LayoutParams;


public class LeftSlidingMenu extends FrameLayout{
private LinearLayout top_layout;
private LinearLayout bootom_layout;
private boolean SlidingFlag=false;//抽屉状态标志,默认关闭
private int Max_width=0;//抽屉打开的最大宽度
private PointFstartpf=new PointF();//第一次记录起点的坐标
private PointFstartpf2=new PointF();//第二次记录起点的坐标
private PointF overf=new PointF();
private boolean isFirst=true;
public LeftSlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
initview();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (isFirst) {
//将父控件的宽缩小十分之三就是抽屉最大的宽度
Max_width=(int)(getMeasuredWidth()*0.7);
//bootom_layout就是抽屉界面
bootom_layout.setLayoutParams(new FrameLayout.LayoutParams(Max_width,FrameLayout.LayoutParams.MATCH_PARENT));
//top_layout是 主界面
top_layout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT));
//将布局添加到自定义里面
addView(bootom_layout);
addView(top_layout);
}
isFirst=false;
}
private void initview() {
// TODO Auto-generated method stub
//设置底部layout 的属性
bootom_layout=new LinearLayout(getContext());
bootom_layout.setOrientation(LinearLayout.VERTICAL);
//设置top_layout属性
top_layout=new LinearLayout(getContext());
top_layout.setOrientation(LinearLayout.VERTICAL);
top_layout.setBackgroundColor(Color.BLUE);
}
public void setBottomView(View v){
v.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
bootom_layout.addView(v);
}
public void setTopView(View v){
v.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
top_layout.addView(v);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction()==MotionEvent.ACTION_DOWN) {
startpf.x=ev.getX();
startpf.y=ev.getY();
startpf2.x=ev.getX();
startpf2.y=ev.getY();
}else if (ev.getAction()==MotionEvent.ACTION_MOVE) {
overf.x=ev.getX();
overf.y=ev.getY();
float disx=overf.x-startpf.x;
float disy=overf.y-startpf.y;
//根据正余弦定理来判断  水平滑动或者是垂直滑动,
//也就是判断滑动的倾斜度,倾斜度越大,划不动,小则可以拉动抽屉,以y轴为原点;
if (Math.abs(disx)/2-Math.abs(disy)>0) {
Log.e("tag","11111");
}else {//垂直状态--》抽屉应该关闭
// 通过抽屉的开关来判断上层可否移动
if (!SlidingFlag) {
return super.dispatchTouchEvent(ev);
}else {
return true;
}
}
//设置一个边界值:防止手指按下出现抽屉抖动的情况
// if(Math.abs(disX)<10){
// return super.dispatchTouchEvent(ev);
// }
//根据手指滑动的x轴移动的距离的正负,判断抽屉打开的方向
if (disx>0) {//大于0  从左往右滑动
//获取到top_layout的属性 
FrameLayout.LayoutParams topparms=(LayoutParams)top_layout.getLayoutParams();
//滑动距离超过最大边距,将最大边距设置给滑动距离
if (topparms.leftMargin>=Max_width) {
disx=Max_width;
SlidingFlag=true;//抽屉开启
}
topparms.leftMargin=(int) disx;//将移动的距离设置为左边距
topparms.rightMargin=(int) -disx;
top_layout.setLayoutParams(topparms);//将属性设置给top_layout
}else if (disx<0) {
//获取到top_layout的属性  
FrameLayout.LayoutParams topparms=(LayoutParams)top_layout.getLayoutParams();
if (topparms.leftMargin<=0) {
disx=0;
SlidingFlag=false;
}
//滑动的多少,顶部+底部=1,  顶部多点的话,底部就会多点
topparms.leftMargin=(int) (topparms.leftMargin-Math.abs(disx));
topparms.rightMargin=-topparms.leftMargin;
top_layout.setLayoutParams(topparms);
startpf.x=overf.x;//将移动后的坐标赋值给初始坐标,解决再次移动的问题
}
requestLayout();//刷新界面
return true;
}else if (ev.getAction()==MotionEvent.ACTION_UP) {
//区分是点击还是滑动
int disX=(int)Math.abs(ev.getX()-startpf2.x);
//disX>10 为了不让触碰屏幕,抽屉有轻微的抖动
if (disX>10) {
//以底部linear的宽度的一半为分割线,超过分割线,抽屉自动打开或关闭
FrameLayout.LayoutParams topparms=(LayoutParams)top_layout.getLayoutParams();
if (topparms.leftMargin>Max_width/2) {
topparms.leftMargin=Max_width;
topparms.rightMargin=-Max_width;
SlidingFlag=true;
}else {
//抽屉关闭
topparms.leftMargin=0;
topparms.rightMargin=0;
SlidingFlag=false;
}
top_layout.setLayoutParams(topparms);
requestLayout();
return true;
}
}
return super.dispatchTouchEvent(ev);
}
}

activity_main

<RelativeLayout 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"
     >
  <com.example.zidingyict.LeftSlidingMenu
     android:id="@+id/myslidingMenu"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     />
</RelativeLayout>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值