您的位置:首页 > 移动开发 > Android开发

自定义View开关按钮

2017-01-12 17:39 573 查看
今天来介绍下如何自定义类似iOS的按钮。



switch.gif

要想自定义View,需要了解自定义View的相关步骤,一般来说自定义View需要实现以下操作:



自定义view步骤


自定义切换按钮


1.自定义属性


根据自定义View中需要用户设置的属性,来构造自定义属性,直接在xml资源文件中的
resources
标签下声明:
<declare-styleable name="Switch">
<attr name="checked" format="reference|boolean"/>
<attr name="switchOnColor" format="reference|color"/>
<attr name="switchOffColor" format="reference|color"/>
<attr name="spotOnColor" format="reference|color"/>
<attr name="spotOffColor" format="reference|color"/>
<attr name="spotPadding" format="reference|dimension"/>
<attr name="duration" format="reference|integer" />
</declare-styleable>


并在继承View类的
Switch
类中声明全局变量:
private int switchOnColor;
private int switchOffColor;
private int spotOnColor;
private int spotOffColor;
private int spotPadding;
private boolean mChecked;
private int duration;


2.初始化构造函数


一般来说,如果自定义View用于在布局文件声明,则必须初始化覆盖基类的两个参数的构造函数;其他带参构造函数,根据需求进行初始化。

在构造函数中通过
obtainStyledAttributes()
方法获取用户设置的属性值:
public Switch(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Switch);
switchOnColor = a.getColor(R.styleable.Switch_switchOnColor, DEFAULT_SWITCH_ON_COLOR);
switchOffColor = a.getColor(R.styleable.Switch_switchOffColor, DEFAULT_SWITCH_OFF_COLOR);
spotOnColor = a.getColor(R.styleable.Switch_spotOnColor, DEFAULT_SPOT_ON_COLOR);
spotOffColor = a.getColor(R.styleable.Switch_spotOffColor, DEFAULT_SPOT_OFF_COLOR);
spotPadding = a.getDimensionPixelSize(R.styleable.Switch_spotPadding, dp2px(DEFAULT_SPOT_PADDING));
duration = a.getInteger(R.styleable.Switch_duration, ANIMATION_DURATION);
mChecked = a.getBoolean(R.styleable.Switch_checked, false);
a.recycle();

state = mChecked ? State.SWITCH_ON : State.SWITCH_OFF;
setClickable(true);
}


3.测量View——onMeasure


onMeasure
方法是决定自定义View布局大小的关键,可通过
MeasureSpec
获取父布局分配给子布局的大小及布局模式。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

int width = dp2px(DEFAULT_WIDTH) + getPaddingLeft() + getPaddingRight();
int height = dp2px(DEFAULT_HEIGHT) + getPaddingTop() + getPaddingBottom();

if (widthSpecMode != MeasureSpec.AT_MOST) {
width = Math.max(width, widthSpecSize);
}

if (heightSpecMode != MeasureSpec.AT_MOST) {
height = Math.max(height, heightSpecSize);
}

setMeasuredDimension(width, height);
}


4.给定View高宽——setMeasuredDimension


通过
setMeasuredDimension
方法设置自定义布局想要的View大小。代码如上所示。

5.绘制View——onDraw


最核心的方法莫过于
onDraw
了,
onDraw
是绘制View的关键,结合
ValueAnimator
ObjectAnimator
等可实现View的动画效果。
private void animateToCheckedState() {
valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(duration);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPos = (float) animation.getAnimatedValue();
invalidate();
}
});

valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
isMoving = true;
}

@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
isMoving = false;
}
});

if (!valueAnimator.isRunning()) {
valueAnimator.start();
currentPos = 0;
}
}


6.回调监听


切换按钮的回调,主要体现在开关状态的变化:
public interface OnCheckedChangeListener {
/**
* Called when the checked state of a switch has changed.
*
* @param s The switch whose state has changed.
* @param isChecked The new checked state of switch.
*/
void onCheckedChanged(Switch s, boolean isChecked);
}


7.手势处理


本项目中并未使用onTouchEvent方法处理手势监听,而是覆盖了父类的
performClick
方法,同时保证了
OnClickListener
的生效。
@Override
public boolean performClick() {
toggle();

final boolean handled = super.performClick();
if (!handled) {
// View only makes a sound effect if the onClickListener was
// called, so we'll need to make one here instead.
playSoundEffect(SoundEffectConstants.CLICK);
}

return handled;
}


作者 @fynn


项目地址 github
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android studio android