@RemoteView
public class Button extends TextView {
public Button(Context context) {
this(context, null);
} public Button(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.buttonStyle);
} public Button(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(Button. class.getName());
} @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(Button. class.getName());
}
}

是直接继承于TextView,所不同的是在构造方法中添加了Button的样式,并且在初始化可见性方面交由Button类自己来处理。虽然Button的实现比较简单,但是它的子类并不是这样。看一下:

直接子类只有有一个,CompoundButton。它是一个抽象类,而实现这个类的控件正是
CheckBox

RadioButton

Switch

ToggleButton
这四个,所以先重点说一下它。源码如下:

/**
* <p>
* A button with two states, checked and unchecked. When the button is pressed
* or clicked, the state changes automatically.
* </p>
*
* <p><strong>XML attributes </strong></p>
* <p>
* See {@link android.R.styleable#CompoundButton
* CompoundButton Attributes}, {@link android.R.styleable#Button Button
* Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link
* android.R.styleable #View View Attributes}
* </p>
*/
public abstract class CompoundButton extends Button implements Checkable {
private boolean mChecked ;
private int mButtonResource ;
private boolean mBroadcasting ;
private Drawable mButtonDrawable;
private OnCheckedChangeListener mOnCheckedChangeListener;
private OnCheckedChangeListener mOnCheckedChangeWidgetListener ; private static final int[] CHECKED_STATE_SET = {
R.attr.state_checked
}; public CompoundButton(Context context) {
this(context, null);
} public CompoundButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public CompoundButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); TypedArray a =
context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0); Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);
if (d != null ) {
setButtonDrawable(d);
} boolean checked = a
.getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false);
setChecked(checked); a.recycle();
} public void toggle() {
setChecked(! mChecked);
} @Override
public boolean performClick() {
/*
* XXX: These are tiny, need some surrounding 'expanded touch area',
* which will need to be implemented in Button if we only override
* performClick()
*/ /* When clicked, toggle the state */
toggle();
return super .performClick();
} @ViewDebug.ExportedProperty
public boolean isChecked() {
return mChecked ;
} /**
* <p>Changes the checked state of this button.</p>
*
* @param checked true to check the button, false to uncheck it
*/
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED ); // Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting ) {
return;
} mBroadcasting = true ;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener .onCheckedChanged(this, mChecked);
} mBroadcasting = false ;
}
} /**
* Register a callback to be invoked when the checked state of this button
* changes.
*
* @param listener the callback to call on checked state change
*/
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
} /**
* Register a callback to be invoked when the checked state of this button
* changes. This callback is used for internal purpose only.
*
* @param listener the callback to call on checked state change
* @hide
*/
void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) {
mOnCheckedChangeWidgetListener = listener;
} /**
* Interface definition for a callback to be invoked when the checked state
* of a compound button changed.
*/
public static interface OnCheckedChangeListener {
/**
* Called when the checked state of a compound button has changed.
*
* @param buttonView The compound button view whose state has changed.
* @param isChecked The new checked state of buttonView.
*/
void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
} /**
* Set the background to a given Drawable, identified by its resource id.
*
* @param resid the resource id of the drawable to use as the background
*/
public void setButtonDrawable(int resid) {
if (resid != 0 && resid == mButtonResource ) {
return;
} mButtonResource = resid; Drawable d = null;
if (mButtonResource != 0) {
d = getResources().getDrawable(mButtonResource );
}
setButtonDrawable(d);
} /**
* Set the background to a given Drawable
*
* @param d The Drawable to use as the background
*/
public void setButtonDrawable(Drawable d) {
if (d != null ) {
if (mButtonDrawable != null) {
mButtonDrawable.setCallback(null);
unscheduleDrawable( mButtonDrawable);
}
d.setCallback( this);
d.setVisible(getVisibility() == VISIBLE, false);
mButtonDrawable = d;
setMinHeight(mButtonDrawable .getIntrinsicHeight());
} refreshDrawableState();
} @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(CompoundButton.class .getName());
event.setChecked( mChecked);
} @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(CompoundButton.class .getName());
info.setCheckable( true);
info.setChecked( mChecked);
} @Override
public int getCompoundPaddingLeft() {
int padding = super.getCompoundPaddingLeft();
if (!isLayoutRtl()) {
final Drawable buttonDrawable = mButtonDrawable;
if (buttonDrawable != null) {
padding += buttonDrawable.getIntrinsicWidth();
}
}
return padding;
} @Override
public int getCompoundPaddingRight() {
int padding = super.getCompoundPaddingRight();
if (isLayoutRtl()) {
final Drawable buttonDrawable = mButtonDrawable;
if (buttonDrawable != null) {
padding += buttonDrawable.getIntrinsicWidth();
}
}
return padding;
} /**
* @hide
*/
@Override
public int getHorizontalOffsetForDrawables() {
final Drawable buttonDrawable = mButtonDrawable ;
return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0;
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable ;
if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK ;
final int drawableHeight = buttonDrawable.getIntrinsicHeight();
final int drawableWidth = buttonDrawable.getIntrinsicWidth(); int top = 0;
switch (verticalGravity) {
case Gravity.BOTTOM :
top = getHeight() - drawableHeight;
break;
case Gravity.CENTER_VERTICAL :
top = (getHeight() - drawableHeight) / 2;
break;
}
int bottom = top + drawableHeight;
int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
int right = isLayoutRtl() ? getWidth() : drawableWidth; buttonDrawable.setBounds(left, top, right, bottom);
buttonDrawable.draw(canvas);
}
} @Override
protected int[] onCreateDrawableState(int extraSpace) {
final int [] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
} @Override
protected void drawableStateChanged() {
super.drawableStateChanged(); if (mButtonDrawable != null) {
int[] myDrawableState = getDrawableState(); // Set the state of the Drawable
mButtonDrawable.setState(myDrawableState); invalidate();
}
} @Override
protected boolean verifyDrawable(Drawable who) {
return super .verifyDrawable(who) || who == mButtonDrawable;
} @Override
public void jumpDrawablesToCurrentState() {
super.jumpDrawablesToCurrentState();
if (mButtonDrawable != null) mButtonDrawable.jumpToCurrentState();
} static class SavedState extends BaseSavedState {
boolean checked ; /**
* Constructor called from {@link CompoundButton#onSaveInstanceState()}
*/
SavedState(Parcelable superState) {
super(superState);
} /**
* Constructor called from {@link #CREATOR}
*/
private SavedState(Parcel in) {
super(in);
checked = (Boolean)in.readValue( null);
} @Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeValue( checked);
} @Override
public String toString() {
return "CompoundButton.SavedState{"
+ Integer.toHexString(System.identityHashCode(this))
+ " checked=" + checked + "}" ;
} public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
} public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
} @Override
public Parcelable onSaveInstanceState() {
// Force our ancestor class to save its state
setFreezesText( true);
Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss. checked = isChecked();
return ss;
} @Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss. checked);
requestLayout();
}
}

先从构造方法开始,在构造方法中,

public CompoundButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); TypedArray a =
context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.CompoundButton, defStyle, 0); Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button);
if (d != null ) {
setButtonDrawable(d);
} boolean checked = a
.getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false);
setChecked(checked); a.recycle();
}

先是从attrs中读取定义的属性,一个是Drawable用于设置背景;一个是布尔类型变量用于判断是否check过。设置背景使用的是setButtonDrawable()方法,代码如下:

/**
* Set the background to a given Drawable
*
* @param d The Drawable to use as the background
*/
public void setButtonDrawable(Drawable d) {
if (d != null ) {
if (mButtonDrawable != null) {
mButtonDrawable.setCallback(null);
unscheduleDrawable( mButtonDrawable);
}
d.setCallback( this);
d.setVisible(getVisibility() == VISIBLE, false);
mButtonDrawable = d;
setMinHeight(mButtonDrawable .getIntrinsicHeight());
} refreshDrawableState();
}

这个方法写的就比较完善,可以作为一个学习的典范。首先判断传递过来的Drawable是否为空,如果不为空并且默认的Drawable也不为空,那么取消默认Drawable的callback,然后调用 unscheduleDrawable 方法。这个方法代码如下:

/**
* Unschedule any events associated with the given Drawable. This can be
* used when selecting a new Drawable into a view, so that the previous
* one is completely unscheduled.
*
* @param who The Drawable to unschedule.
*
* @see #drawableStateChanged
*/
public void unscheduleDrawable(Drawable who) {
if (mAttachInfo != null && who != null) {
mAttachInfo.mViewRootImpl .mChoreographer.removeCallbacks(
Choreographer.CALLBACK_ANIMATION, null, who);
}
}

从方法注释中可以看出它的用途,正是更换Drawable时候使用的。接下来开始重新设置Drawable,包括回调、可见性、最小高度。最后调用 refreshDrawableState() 方法,这个是View类的方法,用于更新Drawable状态。

然后再回过头看一下 setChecked (checked) 方法,这个用于设置check,也就是button的点击状态。代码如下:

/**
* <p>Changes the checked state of this button.</p>
*
* @param checked true to check the button, false to uncheck it
*/
public void setChecked( boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED ); // Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting ) {
return;
} mBroadcasting = true ;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener .onCheckedChanged(this, mChecked);
}
mBroadcasting = false ;
}
}

在这个方法中多出了一个接口,这个接口真是check的一个回调接口,代码如下:

/**
* Interface definition for a callback to be invoked when the checked state
* of a compound button changed.
*/
public static interface OnCheckedChangeListener {
/**
* Called when the checked state of a compound button has changed.
*
* @param buttonView The compound button view whose state has changed.
* @param isChecked The new checked state of buttonView.
*/
void onCheckedChanged(CompoundButton buttonView, boolean isChecked);
}

这种回调接口在Android中处处可见,之前的文章也有介绍过。但是在上面的方法,它使用了一个mBroadcasting变量,进而巧妙地避免了重复递归的问题,大家自己感受一下。

然后就是ondraw()方法了,把之前的drawable画出来。代码如下:

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); final Drawable buttonDrawable = mButtonDrawable ;
if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK ;
final int drawableHeight = buttonDrawable.getIntrinsicHeight();
final int drawableWidth = buttonDrawable.getIntrinsicWidth(); int top = 0;
switch (verticalGravity) {
case Gravity.BOTTOM :
top = getHeight() - drawableHeight;
break;
case Gravity.CENTER_VERTICAL :
top = (getHeight() - drawableHeight) / 2;
break;
}
int bottom = top + drawableHeight;
int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
int right = isLayoutRtl() ? getWidth() : drawableWidth; buttonDrawable.setBounds(left, top, right, bottom);
buttonDrawable.draw(canvas);
}
}

看得出来,在onDrawable()方法中,最主要的部分还是如何确定上下左右四个参数。确定完后就可以画出来了。但是,CompoundButton是一个抽象类,并不能直接使用,那看一下它的子类是如何实现的:

1、CheckBox
public class CheckBox extends CompoundButton {
public CheckBox(Context context) {
this(context, null);
} public CheckBox(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.checkboxStyle);
} public CheckBox(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(CheckBox. class.getName());
} @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(CheckBox. class.getName());
}
}

和Button的实现差不多,使用了一个自己的样式。并且也是重写了那两个方法。再来看一下RadioButton,

public class RadioButton extends CompoundButton {

  public RadioButton(Context context) {
this(context, null);
} public RadioButton(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.radioButtonStyle);
} public RadioButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} /**
* {@inheritDoc}
* <p>
* If the radio button is already checked, this method will not toggle the radio button.
*/
@Override
public void toggle() {
// we override to prevent toggle when the radio is already
// checked (as opposed to check boxes widgets)
if (!isChecked()) {
super.toggle();
}
} @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(RadioButton. class.getName());
} @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(RadioButton. class.getName());
}
}

和CheckBox实现差不多,区别在于多重写了一个方法,用于防止按钮被重复点击。另外还有ToggleButton以及Switch,前者实现也比较简单,后者稍微麻烦了一些,感兴趣可以自己分析。

最后切入正题,看看滑动Button要如何实现呢?首先看一下效果图:

 图1-1
  
 图1-2

图1-1所示的滑动Button实现的思路是这样的,背景图片有开和关的文字,一个按钮在其上面左右滑动,遮住相应的部分,使其在一个位置时候只能看到一个开关。

如图1-3,在实现的时候,先画一个开关背景图片只,然后在其上面画一个按钮,滑动开关的时候对上面的按钮进行处理即可。

  准备:

    1、按钮图片
       
      

2、背景图片

       

 编码:

在自定义滑动按钮控件的时候,可以有多种选择,可以继承于Button,也可以继承于Button的子类,也可以继承于View类等。我们知道滑动按钮是
一个很简单的控件,就是左右滑动改变显示内容,不需要其他的额外东西在里面,所以直接继承于View来实现即可。如果继承于系统的一些控件,那么有很多东
西用不到,会造成浪费。

1、定义一个类继承于View,初始化构造方法,在构造方法中加载图片及其信息。

2、重写onMeasure()方法,计算控件的大小。

3、重写onTouchEvent()方法,对滑动事件进行判别处理。

4、定义接口,实现回调。

5、重写onDraw()方法,动态画出按钮。

代码如下:

/**
*
*/
package com.kince.slidebutton; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View; /**
* @author kince
* @category 左右手势滑动button
* @serial 1.0.0
* @since 2014.5.17
* @see http://blog.csdn.net/wangjinyu501
*
*/
public class SlideButton extends View { private Bitmap slideBitMap;// 滑动图片
private Bitmap switchBitMap;// 背景图片 private int slideBitMapWidth;// 滑动图片宽度
private int switchBitMapWidth;// 背景图片宽度
private int switchBitMapHeight;// 背景图片高度 private boolean currentState;// 开关状态
private boolean isSliding = false; // 是否正在滑动中 private int currentX; // 当前开关的位置 private OnToggleStateChangedListener mChangedListener;// 回调接口 /**
* @param context
* 在java代码中直接调用使用此构造方法
*/
public SlideButton(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
} /**
* @param context
* @param attrs
* 在xml中使用要用到这个方法
*/
public SlideButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
} /**
* @param context
* @param attrs
* @param defStyleAttr
* 指定一个样式
*/
public SlideButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initBitmap();
} /**
* @category 加载背景图片以及开关图片 然后获取各自的宽高
*
*/
private void initBitmap() {
// TODO Auto-generated method stub
slideBitMap = BitmapFactory.decodeResource(getResources(),
R.drawable.slide_button_background);
switchBitMap = BitmapFactory.decodeResource(getResources(),
R.drawable.switch_background);
slideBitMapWidth = slideBitMap.getWidth();
switchBitMapWidth = switchBitMap.getWidth();
switchBitMapHeight = switchBitMap.getHeight();
Log.i("switchBitMapWidth", switchBitMapWidth + "");
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(switchBitMapWidth, switchBitMapHeight);// 设置控件的宽高
} @Override
protected void onDraw(Canvas canvas) {
// 绘制button背景图片
canvas.drawBitmap(switchBitMap, 0, 0, null);
// 绘制滑动开关
if (isSliding) {// 如果当前状态是滑动中 则动态绘制开关
int dis = currentX - slideBitMapWidth / 2;
if (dis < 0) {
dis = 0;
} else if (dis > switchBitMapWidth - slideBitMapWidth) {
dis = switchBitMapWidth - slideBitMapWidth;
}
canvas.drawBitmap(slideBitMap, dis, 0, null);
} else {
if (currentState) { // 绘制开关为开的状态
canvas.drawBitmap(slideBitMap, switchBitMapWidth
- slideBitMapWidth, 0, null);
} else { // 绘制开关为关的状态
canvas.drawBitmap(slideBitMap, 0, 0, null);
}
}
super.onDraw(canvas);
} @Override
public boolean onTouchEvent(MotionEvent event) {
// 手势识别 判断滑动方向
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
isSliding = true;
currentX = (int) event.getX();
break; case MotionEvent.ACTION_MOVE:
currentX = (int) event.getX();
Log.i("currentX", currentX + ""); break;
case MotionEvent.ACTION_UP:
isSliding = false;
int bgCenter = switchBitMapWidth / 2;
boolean state = currentX > bgCenter; // 改变后的状态
if (state != currentState && mChangedListener != null) {// 添加回调
mChangedListener.onToggleStateChanged(state);
}
currentState = state;
break;
default:
break;
}
invalidate();
return true;
} public OnToggleStateChangedListener getmChangedListener() {
return mChangedListener;
} public void setmChangedListener(
OnToggleStateChangedListener mChangedListener) {
this.mChangedListener = mChangedListener;
} public boolean isToggleState() {
return currentState;
} public void setToggleState(boolean currentState) {
this.currentState = currentState;
} }

回调接口,

package com.kince.slidebutton;

/**
* @author kince
*
*/
public interface OnToggleStateChangedListener { /**
* @category
* @param state
*/
public void onToggleStateChanged(boolean state); }

Activity代码,

package com.kince.slidebutton;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import android.os.Build; public class MainActivity extends ActionBarActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
} @Override
public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} /**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment implements
OnToggleStateChangedListener { private SlideButton slidebutton; public PlaceholderFragment() {
} @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
slidebutton = (SlideButton) rootView.findViewById(R.id.slidebutton1);
// 设置一下开关的状态
slidebutton.setToggleState(true); // 设置开关的状态为打开
slidebutton.setmChangedListener(this);
return rootView;
} @Override
public void onToggleStateChanged(boolean state) {
// TODO Auto-generated method stub
FragmentActivity activity = getActivity();
if (state) {
Toast.makeText(activity, "开关打开", 0).show();
} else {
Toast.makeText(activity, "开关关闭", 0).show();
}
}
} }

未完待续。

Android SwitchButton(滑动开关)的更多相关文章

  1. 【转】Android SwitchButton(滑动开关)

    原文网址:http://blog.csdn.net/wangjinyu501/article/details/27961303 版本:1.0 日期:2014.5.17 2014.6.1 版权:© 20 ...

  2. Android第三方开源SwitchButton

    Android第三方开源SwitchButton Android SwitchButton是github上的一个第三方开源项目,其项目主页是:https://github.com/kyleduo/Sw ...

  3. 【Android】自己定义控件实现可滑动的开关(switch)

    ~转载请注明来源:http://blog.csdn.net/u013015161/article/details/46704745 介绍 昨天晚上写了一个Android的滑动开关, 即SlideSwi ...

  4. Android 三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现

    android三档自定义滑动开关,禁止点击功能的实现,普通开关网上有很多例子,三档滑动开关的则找了整天都没有相关例子,开始用普通开关的源码修改了自己实现了一个类,但效果不如人意,各种边界情况的算法很难 ...

  5. android 自己定义开关(SwitchButton)

    近期心血来潮,写了一个自己定义仿iPhone的开关. 有须要的同学能够来下载啦.支持点击自己主动滚动,速率能够自己依据须要改动.触摸滚动,大小自己定义,支持改动样式.就不录制动画,就上传了两张图给大家 ...

  6. Android实现Material Design风格的设置页面(滑动开关控件)

    前言 本文链接 http://blog.csdn.net/never_cxb/article/details/50763271 转载请注明出处 參考了这篇文章 Material Design 风格的设 ...

  7. android自定义控件——以滑动开关为例

    0.引言 (1)Android从4.0开始提供了switch的滑动开关效果组件,但是之前版本却没有 (2)很多时候我们写程序,都希望把有用的通用的通用的东西封装起来,以便以后重用. 本文根据组件开发思 ...

  8. Android 自定义的开关按钮——SwitchButton

    本文转自:http://blog.csdn.net/swust_chenpeng/article/details/19967501 我将原文的控件进行了一些修改,去掉了原来控件的外边框,只留下重要的遮 ...

  9. Android自己定义View基础篇(三)之SwitchButton开关

    自己定义View基础篇(二) 自己定义View基础篇(一) 自己定义View原理 我在解说之前,先来看看效果图,有图有真相:(转换gif图片效果太差) 那来看看真实图片: 假设你要更改样式,请改动例如 ...

随机推荐

  1. 【转】 自定义iOS7导航栏背景,标题和返回按钮文字颜色

    原文:http://blog.csdn.net/mad1989/article/details/41516743 UIBarButtonItem,navigationItem,backBarButto ...

  2. 你好,C++(40)7.1 一切指针都是纸老虎:彻底理解指针

    第7章 C++世界的奇人异事 在武侠小说中,初入武林的毛头小子总是要遇到几位奇人,发生几件异事,经过高人的指点,经历一番磨炼,方能武功精进,从新手成长为高手.在C++世界,同样有诸多的奇人异事.在C+ ...

  3. Linux命令——创建删除文件

    创建文件夹 mkdir filename 进入目录文件 cd filename 返回上一级目录 cd ..返回多级目录   cd ../../.. (../表示一级) 创建文件 touch filen ...

  4. ASP.NET程序从IIS6移植到IIS7时出现500.22错误

    最可能的原因:  •    此应用程序在 system.web/httpModules 节中定义配置.  可尝试的操作:  •    将配置迁移到 system.webServer/modules 节 ...

  5. [Python笔记]第四篇:内置函数

    本篇主要内容:内置函数 函数 参考:https://docs.python.org/3.5/library/functions.html 内置函数列表 一.数学运算类 abs(x)求绝对值 >& ...

  6. Python自动化运维之21、CSS

    一.css简介 CSS 是 Cascading Style Sheets的缩写,称为层叠样式表,用来设计网页的样式布局,以及大小来适应不同的屏幕等,使网页的样式和网页数据分离, 二.导入css 导入c ...

  7. iOS开发——C篇&数组与指针

    2015-07-17 13:23 编辑 前面我们介绍了关于C语言的内存分配问题,下面我们就开始介绍关于C语言的两个非常重要的知识点:数组与指针 数组与指针其实不仅仅是再C语言中,再OC中(当然OC是内 ...

  8. IPv6套接字地址结构

    IPv6套接字地址结构 struct in6_addr{ unit8_t sa_addr[16]; }; #define SIN6_LEN struct sockaddr_in6{ unit8_t s ...

  9. 【JavsScript】关于javascript的路线

    Client JS: Level 1 基本对象的掌握----------------------------------------->Library(兼容)/Widget(UI+功能)---- ...

  10. hadoop安装问题记录

    start-yarn.sh 启动正常,但是无法访问网页http://localhost:8088/cluster 原因: 可能是ipv6 的问题 解决方法: http://stackoverflow. ...