android_94_自定义ToggleButton
2017-01-23 20:39
375 查看
效果:
枚举:
自定义View与ViewGroup的区别
示意图:
getX();得到的是 View内部的坐标系;原点在View内的左上角
注意:文字是特殊情况,
getRawX();得到的是 屏幕坐标系:原点在屏幕的左上角
布局文件:
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.sg31.sgtogglebutton.MainActivity" >
<com.sg31.sgtogglebutton.SGToogleButton
android:id="@+id/toggleBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
主控制器:
package com.sg31.sgtogglebutton;
import com.sg31.sgtogglebutton.SGToogleButton.OnToggleStateChangeLisener;
import com.sg31.sgtogglebutton.SGToogleButton.ToggleState;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity {
private SGToogleButton toggleBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initToggleButton();
}
private void initToggleButton() {
toggleBtn = (SGToogleButton)findViewById(R.id.toggleBtn);
toggleBtn.setBgImgResource(R.drawable.onimg2);
toggleBtn.setSlideImgResource(R.drawable.slideimg);
toggleBtn.setToggleState(ToggleState.Closed);
toggleBtn.setOnToggleStateChangeLisener(new OnToggleStateChangeLisener() {
@Override
public void onToggleStateChanged(ToggleState state) {
// TODO Auto-generated method stub
System.out.println(state==ToggleState.Open?"open":"closed");
}
});
}
}
自定义ToggleButton
package com.sg31.sgtogglebutton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class SGToogleButton extends View {
// 状态枚举
public enum ToggleState{
Open,Closed
}
// 代理
private OnToggleStateChangeLisener lisener;
private ToggleState toggleSate;
private Bitmap slideImg;
private Bitmap bgImg;
private int fingerX;
private boolean isSliding;
public interface OnToggleStateChangeLisener{
void onToggleStateChanged(ToggleState state);
}
public void setOnToggleStateChangeLisener(OnToggleStateChangeLisener lisener) {
this.lisener = lisener;
}
// 构造方法
public SGToogleButton(Context context) {
super(context);
}
public SGToogleButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 供外界调用
public void setBgImgResource(int imgID) {
bgImg = BitmapFactory.decodeResource(getResources(), imgID);
}
// 供外界调用
public void setSlideImgResource(int imgID) {
slideImg = BitmapFactory.decodeResource(getResources(), imgID);
}
// 供外界调用
public void setToggleState(ToggleState state) {
toggleSate = state;
}
// 自定义View的第2步,onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(bgImg.getWidth(), bgImg.getHeight());
}
// 自定义View的第3步,onDraw方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1.绘制背景图 在 View中的位置 (画图可以不用Paint)
canvas.drawBitmap(bgImg, 0, 0, null);
// 2根据状态及变量,进行绘制滑块
if (isSliding) {
int slideImgX = fingerX - slideImg.getWidth()/2;
if (slideImgX < 0) {
// 防止左边越界
slideImgX = 0;
}
if (slideImgX > bgImg.getWidth() - slideImg.getWidth()) {
// 防止右边越界
slideImgX = bgImg.getWidth() - slideImg.getWidth();
}
canvas.drawBitmap(slideImg, slideImgX, 0, null);
} else {
// 抬起时:要么关,要么开
if (toggleSate == ToggleState.Open) {
// 背景图片: 左是开, 右是关
canvas.drawBitmap(slideImg, 0, 0, null);
} else {
canvas.drawBitmap(slideImg, bgImg.getWidth() - slideImg.getWidth(), 0, null);
}
}
}
// 自定义View的第4步,onTouchEvent方法
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("sg__touch");
// 得到按下点,在View自己内部的坐标(相对于View自身的左上角)
fingerX = (int)event.getX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
{
// 只要按下,就标记为滑动
isSliding = true;
}
break;
case MotionEvent.ACTION_MOVE:
{
}
break;
case MotionEvent.ACTION_UP:
{
isSliding = false;
int toggleCenterX = bgImg.getWidth()/2;
if (fingerX > toggleCenterX) {
// 如果用户手指按下的地方,在view的中心线之后面,则表示 滑块从左往右,从开到闭
// 只有不是闭的时候,才要关闭
if (toggleSate != ToggleState.Closed) {
toggleSate = ToggleState.Closed;
// 通知
if (lisener != null) {
lisener.onToggleStateChanged(toggleSate);
}
}
} else {
// 如果用户手指按下的地方,在view的中心线之前面,则表示 滑块从右往左,从闭到开
// 只有不是开的时候,才要打开
if (toggleSate != ToggleState.Open) {
toggleSate = ToggleState.Open;
// 通知
if (lisener != null) {
lisener.onToggleStateChanged(toggleSate);
}
}
}
}
break;
default:
break;
}
// 非常重要的方法,不然没法更新界面
invalidate();
// 自己要处理,所以返回true
return true;
}
}
枚举:
自定义View与ViewGroup的区别
示意图:
getX();得到的是 View内部的坐标系;原点在View内的左上角
注意:文字是特殊情况,
getRawX();得到的是 屏幕坐标系:原点在屏幕的左上角
布局文件:
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.sg31.sgtogglebutton.MainActivity" >
<com.sg31.sgtogglebutton.SGToogleButton
android:id="@+id/toggleBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
主控制器:
package com.sg31.sgtogglebutton;
import com.sg31.sgtogglebutton.SGToogleButton.OnToggleStateChangeLisener;
import com.sg31.sgtogglebutton.SGToogleButton.ToggleState;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity {
private SGToogleButton toggleBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initToggleButton();
}
private void initToggleButton() {
toggleBtn = (SGToogleButton)findViewById(R.id.toggleBtn);
toggleBtn.setBgImgResource(R.drawable.onimg2);
toggleBtn.setSlideImgResource(R.drawable.slideimg);
toggleBtn.setToggleState(ToggleState.Closed);
toggleBtn.setOnToggleStateChangeLisener(new OnToggleStateChangeLisener() {
@Override
public void onToggleStateChanged(ToggleState state) {
// TODO Auto-generated method stub
System.out.println(state==ToggleState.Open?"open":"closed");
}
});
}
}
自定义ToggleButton
package com.sg31.sgtogglebutton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class SGToogleButton extends View {
// 状态枚举
public enum ToggleState{
Open,Closed
}
// 代理
private OnToggleStateChangeLisener lisener;
private ToggleState toggleSate;
private Bitmap slideImg;
private Bitmap bgImg;
private int fingerX;
private boolean isSliding;
public interface OnToggleStateChangeLisener{
void onToggleStateChanged(ToggleState state);
}
public void setOnToggleStateChangeLisener(OnToggleStateChangeLisener lisener) {
this.lisener = lisener;
}
// 构造方法
public SGToogleButton(Context context) {
super(context);
}
public SGToogleButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 供外界调用
public void setBgImgResource(int imgID) {
bgImg = BitmapFactory.decodeResource(getResources(), imgID);
}
// 供外界调用
public void setSlideImgResource(int imgID) {
slideImg = BitmapFactory.decodeResource(getResources(), imgID);
}
// 供外界调用
public void setToggleState(ToggleState state) {
toggleSate = state;
}
// 自定义View的第2步,onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(bgImg.getWidth(), bgImg.getHeight());
}
// 自定义View的第3步,onDraw方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1.绘制背景图 在 View中的位置 (画图可以不用Paint)
canvas.drawBitmap(bgImg, 0, 0, null);
// 2根据状态及变量,进行绘制滑块
if (isSliding) {
int slideImgX = fingerX - slideImg.getWidth()/2;
if (slideImgX < 0) {
// 防止左边越界
slideImgX = 0;
}
if (slideImgX > bgImg.getWidth() - slideImg.getWidth()) {
// 防止右边越界
slideImgX = bgImg.getWidth() - slideImg.getWidth();
}
canvas.drawBitmap(slideImg, slideImgX, 0, null);
} else {
// 抬起时:要么关,要么开
if (toggleSate == ToggleState.Open) {
// 背景图片: 左是开, 右是关
canvas.drawBitmap(slideImg, 0, 0, null);
} else {
canvas.drawBitmap(slideImg, bgImg.getWidth() - slideImg.getWidth(), 0, null);
}
}
}
// 自定义View的第4步,onTouchEvent方法
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("sg__touch");
// 得到按下点,在View自己内部的坐标(相对于View自身的左上角)
fingerX = (int)event.getX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
{
// 只要按下,就标记为滑动
isSliding = true;
}
break;
case MotionEvent.ACTION_MOVE:
{
}
break;
case MotionEvent.ACTION_UP:
{
isSliding = false;
int toggleCenterX = bgImg.getWidth()/2;
if (fingerX > toggleCenterX) {
// 如果用户手指按下的地方,在view的中心线之后面,则表示 滑块从左往右,从开到闭
// 只有不是闭的时候,才要关闭
if (toggleSate != ToggleState.Closed) {
toggleSate = ToggleState.Closed;
// 通知
if (lisener != null) {
lisener.onToggleStateChanged(toggleSate);
}
}
} else {
// 如果用户手指按下的地方,在view的中心线之前面,则表示 滑块从右往左,从闭到开
// 只有不是开的时候,才要打开
if (toggleSate != ToggleState.Open) {
toggleSate = ToggleState.Open;
// 通知
if (lisener != null) {
lisener.onToggleStateChanged(toggleSate);
}
}
}
}
break;
default:
break;
}
// 非常重要的方法,不然没法更新界面
invalidate();
// 自己要处理,所以返回true
return true;
}
}
相关文章推荐
- Android 自定义滑动开关ToggleButton
- Android:自定义ToggleButton
- 自定义Button模拟ToggleButton功能,android
- Android 自定义toggleButton
- android-----自定义ToggleButton
- Android自定义View仿IOS选择控件Togglebutton实现
- Android 自定义View---ToggleButton
- Android 自定义ToggleButton
- Android 自定义ToggleButton
- Android 自定义 LinearLayout
- Android Ringtone 自定义铃声介绍
- Android高手进阶教程(三)之----Android 中自定义View的应用.
- Android中使用自定义Adapter(一)
- 新书内容连载(1):自定义Android组件之带图像的TextView
- 【转】Android自定义控件中自定义属性的处理方式
- Android中使用自定义Adapter(二)
- android构建自定义的视图组件
- android自定义列表的实现
- 新书内容连载(1):自定义Android组件之带图像的TextView
- Android自定义View设定到FrameLayout布局中实现多组件显示