Android之自定义控件深入
本文主要讲述两个知识点:popwindow的使用和通过继承View实现一个自定义控件,实现点击,手动按钮的效果.
popwindow的使用
//定义 popupWindow
popWin = new PopupWindow(MainActivity.this);
popWin.setWidth(input.getWidth()); //设置宽度
popWin.setHeight(200); //设置popWin 高度
popWin.setContentView(listView); //为popWindow填充内容
popWin.setOutsideTouchable(true); // 点击popWin 以处的区域,自动关闭 popWin
popWin.showAsDropDown(input, 0, 0);//设置 弹出窗口,显示的位置
自定义控件实现开关拖动按钮
第一步:实现自定义控件要继承view
public class MyToggleButton extends View implements OnClickListener{
第二步:写构造函数并初始化
/**
* 在代码里面创建对象的时候,使用此构造方法
*/
public MyToggleButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
/**
* 在布局文件中声名的view,创建时由系统自动调用。
* @param context 上下文对象
* @param attrs 属性集
*/
public MyToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
/**
* 初始化
*/
private void initView() {
//初始化图片
backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
slideBtn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
//初始化 画笔
paint = new Paint();
paint.setAntiAlias(true); // 打开抗矩齿
//添加onclick事件监听
setOnClickListener(this);
}
第三步:重写方法
/*
* view 对象显示的屏幕上,有几个重要步骤:
* 1、构造方法 创建 对象。
* 2、测量view的大小。 onMeasure(int,int);
* 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。 onLayout();
* 4、绘制 view 的内容 。 onDraw(Canvas)
*/
@Override
/**
* 测量尺寸时的回调方法
*/
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/**
* 设置当前view的大小
* width :view的宽度
* height :view的高度 (单位:像素)
*/
setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());
}
//确定位置的时候调用此方法
//自定义view的时候,作用不大
// @Override
// protected void onLayout(boolean changed, int left, int top, int right,
// int bottom) {
// super.onLayout(changed, left, top, right, bottom);
// }
/**
* 当前开关的状态
* true 为开
*/
private boolean currState = false;
@Override
/**
* 绘制当前view的内容
*/
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
// 绘制 背景
/*
* backgroundBitmap 要绘制的图片
* left 图片的左边届
* top 图片的上边届
* paint 绘制图片要使用的画笔
*/
canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
//绘制 可滑动的按钮
canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint);
}
第四步:监听点击与拖动事件
/**
* 判断是否发生拖动,
* 如果拖动了,就不再响应 onclick 事件
*
*/
private boolean isDrag = false;
@Override
/**
* onclick 事件在View.onTouchEvent 中被解析。
* 系统对onclick 事件的解析,过于简陋,只要有down 事件 up 事件,系统即认为 发生了click 事件
*
*/
public void onClick(View v) {
/*
* 如果没有拖动,才执行改变状态的动作
*/
if(!isDrag){
currState = !currState;
flushState();
}
}
/**
* down 事件时的x值
*/
private int firstX;
/**
* touch 事件的上一个x值
*/
private int lastX;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
firstX = lastX =(int) event.getX();
isDrag = false;
break;
case MotionEvent.ACTION_MOVE:
//判断是否发生拖动
if(Math.abs(event.getX()-firstX)>5){
isDrag = true;
}
//计算 手指在屏幕上移动的距离
int dis = (int) (event.getX() - lastX);
//将本次的位置 设置给lastX
lastX = (int) event.getX();
//根据手指移动的距离,改变slideBtn_left 的值
slideBtn_left = slideBtn_left+dis;
break;
case MotionEvent.ACTION_UP:
//在发生拖动的情况下,根据最后的位置,判断当前开关的状态
if (isDrag) {
int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); // slideBtn
// 左边届最大值
/*
* 根据 slideBtn_left 判断,当前应是什么状态
*/
if (slideBtn_left > maxLeft / 2) { // 此时应为 打开的状态
currState = true;
} else {
currState = false;
}
flushState();
}
break;
}
flushView();
return true;
}
第五步:刷新当前状态
/**
* 刷新当前状态
*/
private void flushState() {
if(currState){
slideBtn_left = backgroundBitmap.getWidth()-slideBtn.getWidth();
}else{
slideBtn_left = 0;
}
flushView();
}
/**
* 刷新当前视力
*/
private void flushView() {
/*
* 对 slideBtn_left 的值进行判断 ,确保其在合理的位置 即 0<=slideBtn_left <= maxLeft
*
*/
int maxLeft = backgroundBitmap.getWidth()-slideBtn.getWidth(); // slideBtn 左边届最大值
//确保 slideBtn_left >= 0
slideBtn_left = (slideBtn_left>0)?slideBtn_left:0;
//确保 slideBtn_left <=maxLeft
slideBtn_left = (slideBtn_left<maxLeft)?slideBtn_left:maxLeft;
/*
* 刷新当前视图 导致 执行onDraw执行
*/
invalidate();
}
第六步:在layout中添加全类名使用
<com.zj.switchbutton.MyTrouggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
运行效果
Android之自定义控件深入的更多相关文章
- Android中自定义控件TextSize属性问题
本文主要说明一个自定义控件添加TextSize属性的坑,刚刚从坑里面爬出来,写个随笔,记录一下: *************************************************** ...
- Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮
原文:Android笔记--自定义控件仿遥控器的圆形上下左右OK圆盘按钮 上面就是几张预览图!代码在最底下 主要就两个步骤,画图.监听点击 1.整个控件基本上是一步步画出来的,重写onDraw方法开始 ...
- android创建自定义控件
新建一个布局title.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xm ...
- 【转】Android中自定义控件的步骤
原文网址:http://blog.csdn.net/lianchen/article/details/48038969 Android开发中难免遇到需要自定义控件的需求,有些是产品的要求在Androi ...
- 程序媛也话Android 之 自定义控件(垂直方向滑动条)
Android里已经有足够多的控件供开发者使用,但有时候我们还是会想要一些不一样的东西,比如一些UI特效,比如一些3D动画,今天就讲讲比较basic的东西:自定义控件. 1.效果图 如果项目里需要一个 ...
- 《转载-两篇很好的文章整合》Android中自定义控件
两篇很好的文章,有相互借鉴的地方,整合到一起收藏 分别转载自:http://blog.csdn.net/xu_fu/article/details/7829721 http://www.cnblogs ...
- Android之自定义控件
开发自定义控件的步骤: 1.了解View的工作原理 2. 编写继承自View的子类 3. 为自定义View类增加属性 4. 绘制控件 5. 响应用户消息 6 .自定义回调函数 一.Vie ...
- Android中自定义控件,三个构造函数
自定义控件时,最好抽象得彻底,并且编写需严谨,因为可能程序中多处都会引用到它,或者提供给团队中的其他人使用. 其一般步骤为: 1.创建控件的类文件,定义其功能逻辑.一般继承自现有控件或者View 2. ...
- Android学习——自定义控件(二)
这篇文章来介绍自定义组合控件,自定义组合控件的应用场景很多,比如当你的UI如下时: 倘若不使用组合控件,则需要在XML文件中声明4个TextView和4个EditText,而使用了组合控件,则只需要四 ...
随机推荐
- SCU 4424(求子集排列数)
A - A Time Limit:0MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Practice ...
- 采用post的方式提交数据
1)说明:
- [Angularjs]单页应用之分页
写在前面 在项目中,用到单页应用的分页,当时想到使用滚动加载的方案,可是几次尝试都没配置成功,闲着无聊就弄了一个demo. 系列文章 [Angularjs]ng-select和ng-options [ ...
- File类的创建,删除文件
File.Create(@"C:\Users\shuai\Desktop\new.txt"); Console.WriteLine("创建成功"); Conso ...
- vc++ 6.0下Glut的配置 及 Glut 框架介绍
2014-04-08 16:18:30 一.配置Glut 学习来源: http://blog.sina.com.cn/s/blog_5f0cf7bd0100c9oa.html 亲测可行. Glut的 ...
- Python socket编程之五:更新分时图
f1.py # -*- coding: utf-8 -*- import socket import struct import sqlalchemy import pandas ########## ...
- smarty 操作符号,大于、小于。。。
eq相等,6 w% x7 w6 |3 _ne.neq不相等,( i" }" ~( `# V( t& C, k; [gt大于,lt小于,gte.ge大于等于,lte.le 小 ...
- C/C++内存分配区
一.起源 C++内存分成5个区,分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 但这个自由存储区这么一听还是模模糊糊的,和堆好像是一样的,还有同学说起这个问题. 二.个人理解 关于自由存 ...
- Model backing a DB Context has changed; Consider Code First Migrations
Model增加一个字段,数据库对应的也手动添加了字段但是运行时报错 The model backing the 'TopLogDbContext' context has changed since ...
- docker commit容器
docker commit 容器ID 镜象REPOSITORY 镜象TAG 如docker commit 52b41c68ac7b registry.lenovows.com:5000/video-a ...