ChekBox的用途我們就不必多說了,算是一個很古老的控件了,何其類似的還有RadioButton,這個東西因為我目前還沒寫出來,所以用了別人的一個lib,這下面會說到。順便說一句,如果你的app是在5.0環境下編譯的,那么你用傳統的checkbox時,你會發現checkbox在低版本機子上運行出來的樣子和以前不同了,雖然沒有動畫效果,但樣子和5.0以上的checkbox還是很像的。
最小尺寸
48 x 48
開源lib中對於不同的屏幕做了不同大小的對勾圖片,應該能滿足高清屏的要求。至於不可用狀態目前還沒做,其實也就是繼承下isEnable()方法,但是因為做出來的效果我不是很滿意,所以就僅僅試了試,沒真的放出來。
一、導入到自己的工程中
要用這個控件還是得添加開源項目的支持,開源項目地址:
我維護的:https://github.com/shark0017/MaterialDesignLibrary
原版本:https://github.com/navasmdc/MaterialDesignLibrary
大家可以選擇一個下載,反正兩個版本都是我和原作者融合后的東西,差別不大。
添加lib支持后我們就可以用這個控件了,放入布局文件前還是要寫命名空間的。
xmlns:app="http://schemas.android.com/apk/res-auto"
<com.gc.materialdesign.views.CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" />
由於我沒有做可視化的效果,所以在編譯器中沒辦法實時顯示狀態,默認就是一個透明的view。如果大家想在編譯器中看個大概的樣子,可以給它通過background=“#xxxxxx”添加個背景顏色。
真實運行的效果:
二、在布局文件中設定各種屬性
app:checked="true" 是否被選中,默認沒被選中
android:background="#ff0000" 設定checkbox的顏色,默認是綠色
android:layout_width="100dp" 設定checkbox這個view整體的大小,和里面的方框無關。注意看圖中按壓時陰影的大小
android:layout_height="100dp"
app:checkBoxSize="40dp" 設定checkbox里面方框的大小
三、通過代碼設定各種屬性
public class CheckBoxTest extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.checkbox); CheckBox checkBox = (CheckBox)findViewById(R.id.checkBox01); checkBox.setChecked(true);// 設定初始為選中的狀態 checkBox.setBackgroundColor(0xffff0000);// 設置checkbox的顏色 checkBox.setBackgroundColor(getResources().getColor(R.color.orange));// 設置背景色 checkBox.setCheckBoxSize(35.5f);// 設置方框的大小 // 監聽選中的事件 checkBox.setOncheckListener(new OnCheckListener() { @Override public void onCheck(boolean isChecked) { // TODO 自動生成的方法存根 System.out.println("isChecked = "+ checkBox05.isChecked()); Toast.makeText(CheckBoxTest.this, "checkbox status = "+isChecked, 0).show(); } }); } }
四、補充:RadioButton
這個控件是從另一個開源項目中得到的,那個lib中其他的控件都做的不好,就這個做的十分精細。具體的測試和修改我沒去做,下面僅僅給出源碼,由大家自行修改吧,其實可以修改的地方還是蠻多的。
lib地址:https://github.com/keithellis/MaterialWidget
源碼如下:
dimen.xml
這里是默認的屬性,包括長寬啥的,這些值照理說都應該可以在java代碼中定制的。
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- RadioButton Default --> <dimen name="radio_width">48dp</dimen> <dimen name="radio_height">48dp</dimen> <dimen name="radio_border_radius">10dp</dimen> <dimen name="radio_thumb_radius">6dp</dimen> <dimen name="radio_ripple_radius">24dp</dimen> <dimen name="radio_stroke_width">2dp</dimen> <color name="radio_color">#6d6d6d</color> <color name="radio_checked_color">#55b03d</color> </resources>
可以定制的屬性,這里就兩個,蠻少的。請大家自行添加修改吧~
<!-- RadioButton Attribute --> <declare-styleable name="RadioButton"> <attr name="radio_color" format="color"/> <attr name="radio_checked_color" format="color"/> </declare-styleable>
RadioButton.java
從中我們可以看到,這個控件都是被畫出來的,和上面控件用到的lib的構建思路不同。因為是畫出來的,所以我們可以定制的東西更多,擴展性更強,值得細細品味這個類的寫法。
package com.gc.materialdesign.views; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.CompoundButton; import com.gc.materialdesign.R; /** * Created by IntelliJ IDEA. * User: keith. * Date: 14-10-8. * Time: 15:48. */ public class RadioButton extends CompoundButton { private static final long ANIMATION_DURATION = 200;// 動畫持續的時間 private static final int StateNormal = 1; private static final int StateTouchDown = 2; private static final int StateTouchUp = 3; private int mState = StateNormal; private long mStartTime; private int mColor; private int mCheckedColor; private int mRadioWidth;// 寬度 private int mRadioHeight;// 高度 private int mBorderRadius; private int mThumbRadius; private int mRippleRadius; private int mStrokeWidth; private Rect mFingerRect; private boolean mMoveOutside; private Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint ripplePaint = new Paint(Paint.ANTI_ALIAS_FLAG); public RadioButton(Context context) { this(context, null); } public RadioButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RadioButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.RadioButton); mColor = attributes.getColor(R.styleable.RadioButton_radio_color, getResources().getColor(R.color.radio_color)); mCheckedColor = attributes.getColor(R.styleable.RadioButton_radio_checked_color, getResources().getColor(R.color.radio_checked_color)); attributes.recycle(); mRadioWidth = getResources().getDimensionPixelSize(R.dimen.radio_width); mRadioHeight = getResources().getDimensionPixelSize(R.dimen.radio_height); mBorderRadius = getResources().getDimensionPixelSize(R.dimen.radio_border_radius); mThumbRadius = getResources().getDimensionPixelSize(R.dimen.radio_thumb_radius); mRippleRadius = getResources().getDimensionPixelSize(R.dimen.radio_ripple_radius); mStrokeWidth = getResources().getDimensionPixelSize(R.dimen.radio_stroke_width); thumbPaint.setColor(mCheckedColor); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { widthMeasureSpec = MeasureSpec.makeMeasureSpec(measureWidth(widthMeasureSpec), MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec(measureHeight(heightMeasureSpec), MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } private int measureWidth(int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { if (specSize < mRadioWidth) { result = mRadioWidth; } else { result = specSize; } } else { result = mRadioWidth; } return result; } private int measureHeight(int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { if (specSize < mRadioHeight) { result = mRadioHeight; } else { result = specSize; } } else { result = mRadioHeight; } return result; } @Override public boolean onTouchEvent(MotionEvent event) { if (isEnabled()) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mMoveOutside = false; mState = StateTouchDown; mFingerRect = new Rect(getLeft(), getTop(), getRight(), getBottom()); mStartTime = System.currentTimeMillis(); invalidate(); break; case MotionEvent.ACTION_MOVE: if (!mFingerRect.contains(getLeft() + (int) event.getX(), getTop() + (int) event.getY())) { mMoveOutside = true; mState = StateNormal; mStartTime = System.currentTimeMillis(); invalidate(); } break; case MotionEvent.ACTION_UP: if (!mMoveOutside) { mState = StateTouchUp; setChecked(!isChecked()); mStartTime = System.currentTimeMillis(); invalidate(); } break; case MotionEvent.ACTION_CANCEL: mState = StateNormal; invalidate(); break; } } return true; } private int rippleColor(int color) { int alpha = Math.round(Color.alpha(color) * 0.2f); int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); return Color.argb(alpha, red, green, blue); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int rippleRadius = 0; int thumbRadius = isChecked() ? mThumbRadius : 0; long elapsed = System.currentTimeMillis() - mStartTime; switch (mState) { case StateNormal: break; case StateTouchDown: ripplePaint.setAlpha(255); if (elapsed < ANIMATION_DURATION) { rippleRadius = Math.round(elapsed * mRippleRadius / ANIMATION_DURATION); } else { rippleRadius = mRippleRadius; } postInvalidate(); break; case StateTouchUp: if (elapsed < ANIMATION_DURATION) { int alpha = Math.round((ANIMATION_DURATION - elapsed) * 255 / ANIMATION_DURATION); ripplePaint.setAlpha(alpha); rippleRadius = Math.round((ANIMATION_DURATION - elapsed) * mRippleRadius / ANIMATION_DURATION); if (isChecked()) { thumbRadius = Math.round(elapsed * mThumbRadius / ANIMATION_DURATION); } else { thumbRadius = Math.round((ANIMATION_DURATION - elapsed) * mThumbRadius / ANIMATION_DURATION); } } else { mState = StateNormal; rippleRadius = 0; ripplePaint.setAlpha(0); } postInvalidate(); break; } if (isChecked()) { ripplePaint.setColor(rippleColor(mCheckedColor)); borderPaint.setColor(mCheckedColor); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(mStrokeWidth); } else { ripplePaint.setColor(rippleColor(mColor)); borderPaint.setColor(mColor); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(mStrokeWidth); } canvas.drawCircle(getWidth() / 2, getHeight() / 2, rippleRadius, ripplePaint); canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, borderPaint); canvas.drawCircle(getWidth() / 2, getHeight() / 2, thumbRadius, thumbPaint); } }