Android-自定义开关(ViewGroup版)
虽然实现自定义开关,通常情况下都是继承View,比较合理方便快捷一些
但是我今天想去继承ViewGroup来实现自定义开关来玩玩
效果图:
布局代码:
<!-- 自定义开关ViewGroup版 -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myswitch="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".upgrade.MainActivity"> <custom.view.upgrade.my_switch_viewgroup.MySwitch2
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:background="#33F00000"> </custom.view.upgrade.my_switch_viewgroup.MySwitch2> </RelativeLayout>
效果:
布局代码:
<!-- 自定义开关ViewGroup版 -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:myswitch="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".upgrade.MainActivity"> <custom.view.upgrade.my_switch_viewgroup.MySwitch2
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:background="#33F00000"> <!-- 第一个子控件 -->
<ImageView
android:id="@+id/iv_switch_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/switch_background"/> <!-- 第二个子控件 -->
<ImageView
android:id="@+id/iv_switch_drag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/switch_drag"/> </custom.view.upgrade.my_switch_viewgroup.MySwitch2> </RelativeLayout>
自定义开关继承ViewGroup代码:
package custom.view.upgrade.my_switch_viewgroup; import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup; public class MySwitch2 extends ViewGroup implements View.OnClickListener , View.OnTouchListener { private static final String TAG = MySwitch2.class.getSimpleName(); private View switchBackground;
private View switchGrag; private int switchBackgroundWidth;
private int switchBackgroundHeight;
private int switchGragWidth;
private int switchGragHeight; private boolean onCreate = false; // 开关的状态
private boolean switchStatus; public MySwitch2(Context context, AttributeSet attrs) {
super(context, attrs); // 如果是这样写的话,是给整个粉红色正方形区域都设置了点击事件
// setOnClickListener(this);
} @Override
protected void onFinishInflate() {
super.onFinishInflate(); switchBackground = getChildAt(0);
switchGrag = getChildAt(1); onCreate = true; // 给子控件设置点击事件
switchBackground.setOnClickListener(this);
switchGrag.setOnClickListener(this); // 给子控件设置Touch事件
switchBackground.setOnTouchListener(this);
switchGrag.setOnTouchListener(this);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 测量第一个子控件
LayoutParams switchBgParams = switchBackground.getLayoutParams();
switchBackground.measure(switchBgParams.width, switchBgParams.height); // 测量第二个子控件
LayoutParams switchGragParams = switchGrag.getLayoutParams();
switchGrag.measure(switchGragParams.width, switchGragParams.height); // -2 代表是wrap_content
// Log.d(TAG, "测量方法>>> switchGragParams.width" + switchGragParams.width); // 得到测量后的高和宽
if (onCreate) {
onCreate = false;
switchBackgroundWidth = switchBackground.getMeasuredWidth();
switchBackgroundHeight = switchBackground.getMeasuredHeight();
switchGragWidth = switchGrag.getMeasuredWidth();
switchGragHeight = switchGrag.getMeasuredHeight();
} // 在拖动开关的时候,测量会执行很多次,因为在拖动的过程中,开关Grag会的测量宽度会不断变化
// Log.d(TAG, "测量方法>>> switchBackgroundWidth:" + switchBackgroundWidth + " switchGragWidth:" + switchGragWidth);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 给子控件排版指定位置
switchBackground.layout(
getMeasuredWidth() / 2 - switchBackground.getWidth() / 2,
getMeasuredHeight() / 2 - switchBackground.getHeight() / 2,
switchBackground.getMeasuredWidth() + (getMeasuredWidth() / 2 - switchBackground.getWidth() / 2),
switchBackground.getMeasuredHeight() + (getMeasuredHeight() / 2 - switchBackground.getHeight() / 2)); /*switchGrag.layout(
getMeasuredWidth() / 2 - (switchGrag.getWidth() / 2),
getMeasuredHeight() /2 - (switchGrag.getHeight() / 2),
switchGrag.getMeasuredWidth() + getMeasuredWidth() / 2 - (switchGrag.getWidth() / 2),
switchGrag.getMeasuredHeight() + getMeasuredHeight() /2 - (switchGrag.getHeight() / 2));*/ int gragL = getMeasuredWidth() / 2 - (switchBackground.getWidth() / 2);
int gragT = getMeasuredHeight() / 2 - (switchGrag.getHeight() / 2);
switchGrag.layout(
gragL,
gragT,
switchGrag.getMeasuredWidth() + gragL,
switchGrag.getMeasuredHeight() + gragT); // 动的是两个子控件
// scrollTo(90, 0);
} /**
* 打开开关
* @return
*/
/*private int getOpenSwitch() {
return getMeasuredWidth() / 2;
}*/ /**
* 关闭开关
* @return
*/
/*private int getCloseSwitch() {
return getMeasuredWidth() / 2 - (switchBackground.getWidth() / 2);
}*/ /**
* 开关滑动的按钮
* @param move
*/
private void setScrollMove(int move) { int countValue = (switchBackground.getMeasuredWidth() - switchGrag.getMeasuredWidth()) / 2; int countValue2 = (switchBackgroundWidth - switchGragWidth); // Log.d(TAG, "switchBackgroundWidth:" + switchBackgroundWidth + " switchGragWidth:" + switchGragWidth); Log.d(TAG, "move:" + move + " countValue:" + countValue +
" getMeasuredWidth():" + switchGrag.getMeasuredWidth()
+ " getWidth():" + switchGrag.getWidth() + " countValue2:" +countValue2); if (move < 0) {
move = 0;
} else if (move > countValue2) {
Log.d(TAG, "移动到最右边....");
move = countValue2;
}
// switchGrag.setPadding(move, 0, 0, 0);
setPaddingAction(move);
} /**
* 注意!这个是当前MySwitch2 ViewGroup的Touch事件
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
} /**
* 此方法并不去绘制任何东西,Android自动回去绘制的
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
} /**
* 是否可以点击
*/
private boolean isClick = true; @Override
public void onClick(View v) {
Log.d(TAG, "onClick() >>>>>>>>>>>>>>>> run");
Log.d(TAG, "onClick() isClick:" + isClick);
if (isClick) {
if (!switchStatus) {
// 说明是关闭状态,我要打开
moveResult = (switchBackgroundWidth - switchGragWidth);
} else {
moveResult = 0;
}
switchGrag.setPadding(moveResult, 0, 0, 0);
}
} private float downX;
private int moveResult;
private float downTempX; @Override
public boolean onTouch(View v, MotionEvent event) {
boolean touchResult = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
touchResult = false;
downTempX = downX;
isClick = true;
break;
case MotionEvent.ACTION_MOVE:
moveResult += (int) (event.getX() - downX);
setScrollMove(moveResult);
downX = event.getX(); if (Math.abs(event.getX() - downTempX) > 5) {
// 说明在滑动,就onTouch来消费掉了,不给onClick点击事件了
touchResult = true;
Log.d(TAG, "说明在滑动,就onTouch来消费掉了,不给onClick点击事件了");
isClick = false;
}
break;
case MotionEvent.ACTION_UP:
// int upLeft = 0;
if (moveResult > (switchBackgroundWidth - switchGragWidth) / 2) {
moveResult = switchBackgroundWidth - switchGragWidth;
} else if (moveResult < (switchBackgroundWidth - switchGragWidth) / 2) {
moveResult = 0;
} else if (moveResult <= 0){
moveResult = 0;
}
setPaddingAction(moveResult);
break;
default:
break;
}
return touchResult;
} private void setPaddingAction(int value) {
if (value > (switchBackgroundWidth - switchGragWidth) / 2) {
switchStatus = true;
} else if (value < (switchBackgroundWidth - switchGragWidth) / 2) {
switchStatus = false;
} else if (value <= 0){
switchStatus = false;
}
switchGrag.setPadding(value, 0,0,0);
}
}
Android-自定义开关(ViewGroup版)的更多相关文章
- 【Android - 自定义View】之自定义View浅析
1.概述 Android自定义View / ViewGroup的步骤大致如下: 1) 自定义属性: 2) 选择和设置构造方法: 3) 重写onMeasure()方法: 4) 重写onDraw()方法: ...
- Android自定义ViewGroup(四、打造自己的布局容器)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51500304 本文出自:[openXu的博客] 目录: 简单实现水平排列效果 自定义Layo ...
- Android之探究viewGroup自定义子属性参数的获取流程
通常会疑惑,当使用不同的布局方式时,子view得布局属性就不太一样,比如当父布局是LinearLayout时,子view就能有效的使用它的一些布局属性如layout_weight.weightSum. ...
- android自定义viewgroup之我也玩瀑布流
先看效果图吧, 继上一篇<android自定义viewgroup实现等分格子布局>中实现的布局效果,这里稍微有些区别,每个格子的高度不规则,就是传说的瀑布流布局,一般实现这种效果,要么用第 ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu
示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动, ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]
http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...
- Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果
1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...
- Android 自定义ViewGroup手把手教你实现ArcMenu
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37567907 逛eoe发现这样的UI效果,感觉很不错,后来知道github上有这 ...
- Android -- 自定义ViewGroup实现FlowLayout效果
1,在开发的时候,常在我们的需求中会有这种效果,添加一个商品的一些热门标签,效果图如下: 2,从上面效果可以看得出来,这是一个自定义的ViewGroup,然后实现换行效果,让我们一起来实现一下 自定义 ...
随机推荐
- 智能家居入门DIY——【二、LD3320之语音识别】
前一篇说了一下只有RX,TX,VCC,GND的WIFI模块软串口通讯:在实现了远程观察数据,类似的就可以实现远程控制.接下来说一下近距离控制,很多情况下应用语音识别技术无疑比掏出手机操作要更人性化一些 ...
- Float IP设置
浮动IP: 在做双机的时候,设定的一个IP,通过访问这个IP,具体到后台哪台机器,由系统指定. 浮动IP是随资源一起走的. 就是由软件根据具体情况把该IP设置在某一台机器上,对外提供服务 为了避免因为 ...
- Django学习---组合搜索组件
组合搜索组件 我们都会写博客,写文章之后我们要给文章设置目录,设置类型.之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢? 首先我们先创建3张表,分别存放文章,文 ...
- 206. Reverse Linked List + 92. Reverse Linked List II
▶ 关于单链表翻转的两个问题. ▶ 206. 翻转整个单链表. ● 自己的代码,9 ms,使用了递归. class Solution { public: ListNode* reverseList(L ...
- JS执行删除前的判断
JS执行删除前如何实现判断. 一. <script> function del(){ if(confirm("确认删除吗")){ alert("yes&quo ...
- java后端时间处理工具类,返回 "XXX 前" 的字符串
转自:https://www.cnblogs.com/devise/p/9974672.html 我们经常会遇到显示 "某个之间之前" 的需求(比如各种社交软件,在回复消息时,显示 ...
- ASP.NET中高级程序员 面试题
1. 简要说一下.Net的编译过程. 2.ASP.NET与ASP的区别 3.谈一下ASP.NET页面生命周期 4.ASP.NET程序的运行机制.可以从一个页面的请求到返回的角度谈 5.Javascri ...
- bootargs中ip段各项解释
目标板:合众达的SEED-DVS6467开发板 内核版本:2.6.10 最近同事测试板卡nfs挂载PC的文件系统时出现点问题,PC上ifconfig中显示以太网为eth3,然而板卡启动参数列表相关信息 ...
- LevelDB Version
[LevelDB Version] Version 保存了当前磁盘以及内存中所有的文件信息,一般只有一个Version叫做"current" version(当前版本).Level ...
- Kubernetes的UI界面Kubernetes Dashboard的搭建
1.搭建准备 Kubernetes集群的安装部署 2.搭建过程 2.1.在master节点上创建kubernetes-dashboard.yaml cd /etc/kubernetes vim kub ...