android自定义实现抽屉SlidingDrawer的功能
最近项目中需要实现上拉功能,首先想到的就是Android本身自带的抽屉SlidingDrawer,最后也实现了不过,出现的问题就是设置背景色问题,handler和content是两个不同的部分,这就造成图片要做成两部分,从而产生两个部分图片看起来不是一个整体,而且我这个上拉功能,里面要实现一个水平滚动功能,而SlidingDrawer还有其他的限制,同时官方给出api 17以后,这个功能已经废弃,所以自己自定这样一个上拉功能是必须的。
这里我是继承LinearLayout同时实现GestureDetector.OnGestureListener来实现上拉功能。下面是代码:
package com.example.test; import android.content.Context;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.RelativeLayout; public class PanelBom extends LinearLayout implements GestureDetector.OnGestureListener{ GestureDetector mGesture = null;
private boolean isScrolling = false;
private int MAX_HEIGHT = 80;//拖动的最大高度,当前布局位于父布局下面-80位置,这个仅仅是调试参数,这个变量是动态设置的。
private float mScrollX; // 滑块滑动距离
public PanelBom(Context context) {
super(context);
init();
}
public PanelBom(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化一些参数
public void init(){
mGesture = new GestureDetector(this);
mGesture.setIsLongpressEnabled(false);
setBackgroundResource(R.drawable.button_bar);
} @Override
public boolean onTouchEvent(MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction() && isScrolling == true) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();
// 缩回去
if (layoutParams.bottomMargin < -MAX_HEIGHT / 2) {
new AsynMove().execute(-20);//负--往下
} else {
new AsynMove().execute(20);//正--往上
}
}
return mGesture.onTouchEvent(event);
}
//Touch down时触发
@Override
public boolean onDown(MotionEvent e) {
mScrollX = 0;
isScrolling = false;
// 将之改为true,不然事件不会向下传递.
return true;
}
//Touch了还没有滑动时触发
@Override
public void onShowPress(MotionEvent e) { }
@Override
public boolean onSingleTapUp(MotionEvent e) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
// 说明在上面,要往下
if (layoutParams.bottomMargin >= 0) {
new AsynMove().execute(-20);//负--往下
} else {
new AsynMove().execute(20);//正--往上
}
return true;
}
//Touch了滑动时触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
isScrolling = true;
mScrollX += distanceY;
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)getLayoutParams();
layoutParams.bottomMargin += mScrollX;
if (layoutParams.bottomMargin >= 0) {
isScrolling = false;// 拖过头了不需要再执行AsynMove了
layoutParams.bottomMargin = 0;
} else if (layoutParams.bottomMargin <= -MAX_HEIGHT) {
// 拖过头了不需要再执行AsynMove了
isScrolling = false;
layoutParams.bottomMargin = -MAX_HEIGHT;
}
setLayoutParams(layoutParams);
return false;
}
//Touch了不移动一直Touch down时触发
@Override
public void onLongPress(MotionEvent e) { }
//Touch了滑动一点距离后,up时触发。
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
//异步更新布局的位置
class AsynMove extends AsyncTask<Integer, Integer, Void> {
@Override
protected Void doInBackground(Integer... params) {
int times = 0;
int divi = Math.abs(params[0]);
if (MAX_HEIGHT % divi == 0)// 整除
times = MAX_HEIGHT / Math.abs(params[0]);
else
times = MAX_HEIGHT / divi + 1;// 有余数 for (int i = 0; i < times; i++) {
publishProgress(params[0]);
try {
Thread.sleep(divi);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
if (values[0] < 0) {
layoutParams.bottomMargin = Math.max(layoutParams.bottomMargin + values[0], -MAX_HEIGHT);
} else {
layoutParams.bottomMargin = Math.min(layoutParams.bottomMargin + values[0], 0);
}
setLayoutParams(layoutParams); super.onProgressUpdate(values);
}
}
}
主界面:
package com.example.test; import android.app.Activity;
import android.os.Bundle;
import android.widget.RelativeLayout; public class Main5 extends Activity{ RelativeLayout Parent;
PanelBom panelBom;
RelativeLayout.LayoutParams parentParams;
RelativeLayout.LayoutParams paneBomParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Parent = new RelativeLayout(getApplicationContext());
panelBom = new PanelBom(getApplicationContext());
parentParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
paneBomParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 150);
paneBomParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
paneBomParams.bottomMargin = -80;
Parent.addView(panelBom, paneBomParams);
setContentView(Parent, parentParams);
} }
实现的效果是:
拖拉,点击实现上拉功能,效果图如下:
android自定义实现抽屉SlidingDrawer的功能的更多相关文章
- Android -- 滑式抽屉SlidingDrawer(非原创)
SlidingDrawer(滑动式抽屉)隐藏屏外的内容,并允许用户拖拽一个handle以显示隐藏的内容.SlidingDrawer可以在垂直或者水平使用.它由两个子视图组成:一个是用户拖拽的handl ...
- android 自定义view之选座功能
效果图: 界面比较粗糙,主要看原理. 这个界面主要包括以下几部分 1.座位 2.左边的排数 3.左上方的缩略图 4.缩略图中的红色区域 5.手指移动时跟随移动 6.两个手指缩放时跟随缩放 主要技术点 ...
- Android控件之SlidingDrawer(滑动式抽屉)详解与实例
SlidingDrawer效果想必大家也见到过,它就是1.5模拟器上进入应用程序列表的效果.下面是截图 一.简介 SlidingDrawer隐藏屏外的内容,并允许用户通过handle以显示隐藏内容.它 ...
- Android抽屉(SlidingDrawer --类似android通知栏下拉效果)
Android抽屉(SlidingDrawer)的实现发 - 红黑联盟http://www.2cto.com/kf/201301/182507.html 可动态布局的Android抽屉之基础http: ...
- (转)[原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- [原] Android 自定义View步骤
例子如下:Android 自定义View 密码框 例子 1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能 ...
- [原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义title 之Action Bar
Android 自定义title 之Action Bar 2014-06-29 飞鹰飞龙... 摘自 博客园 阅 10519 转 25 转藏到我的图书馆 微信分享: Action Ba ...
随机推荐
- 打开sa属性报错
--如果打开sa属性报错如下:无法显示请求的对话框.属性IsLocked不可用于“登录名sa".该对象可能没有此属性,也可能是访问权限不足而无法检索 --解决办法:首先用windows登录, ...
- Python 第六篇(中):面向对象编程中级篇
面向对象编程中级篇: 编程思想概述: 面向过程:根据业务逻辑从上到下写垒代码 #最low,淘汰 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 #混口饭吃 def add(ho ...
- 07-IOSCore - CoreData补充、音频视频
xml被plist取代了 数据库被coredata取代了 一.Core Data 高级补充 1. Core Data 本质是什么?操作数据库的数据 ORM Object Relationship M ...
- xend调用xenstore的出错揭秘
近期发现几例问题,均是xend里面报了同一个错误 File "/usr/lib64/python2.4/site-packages/xen/xend/xenstore/xstransact. ...
- Java:Java快速入门
链接地址:http://www.cnblogs.com/happyframework/p/3332243.html 你好,世界! 源代码组织方式 Java程序由package+class组成,pack ...
- BZOJ 2750: [HAOI2012]Road( 最短路 )
对于每个点都跑最短路, 然后我们得到了个DAG, 在这DAG上更新每条边的答案. 考虑e(u, v)∈DAG对答案的贡献: 假设从S到u得路径数为A[u], 从v出发到达任意点的路径数为B[v], ...
- 复合文档的二进制存储格式研究[ole存储结构](word,xls,ppt...)[转]
复合文档文件格式研究 前 言 复合文档(Compound Document) 是一种不仅包含文本而且包括图形.电子表格数据.声音.视频图象以及其它信息的文档.可以把复合文档想象成一个所有者,它装着 ...
- Oracle数据库top10物理段
select owner, name, type, mega, tbs from (select owner, case when ...
- VC 2005 解决方案的目录结构设置和管理
VC 2005 解决方案的目录结构设置和管理 Roger (roger2yi@gmail.com) 一个中等规模的解决方案通常都会包含多个项目,其中一些项目产出静态库,一些产出动态库,一些用于 ...
- Androidclient与服务端(jsp)之间json的传输与解析【附效果图附源代码】
近期有个项目须要用到json的传输,之前不是太了解,在网上找了些相关资料,写了一个小小的demo,能够实现基本功能:androidclient发送json到服务端,服务端使用jsp接收,解析后以jso ...