Back to project page AlertDialogPro.
The source code is released under:
Apache License
If you think the Android project AlertDialogPro listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.alertdialogpro.material; //from w ww . j a v a 2s. com import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v7.internal.widget.TintManager; import android.support.v7.internal.widget.TintTypedArray; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.widget.Checkable; import android.widget.TextView; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Compatible CheckedTextView for Pre-Lollipop devices. Draw checkMark at start. */ public class CheckedTextViewCompat extends TextView implements Checkable { private static final int[] CHECKED_TEXT_VIEW_ATTRS = new int[]{ android.R.attr.checked, android.R.attr.checkMark }; private boolean mChecked; private int mCheckMarkResource; private Drawable mCheckMarkDrawable; private int mBasePadding; private int mCheckMarkWidth; private boolean mNeedRequestlayout; private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; private final TintManager mTintManager; private Field mPaddingLeftFeild; private Field mPaddingRightFeild; public CheckedTextViewCompat(Context context) { this(context, null); } public CheckedTextViewCompat(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CheckedTextViewCompat(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setBasePadding(isCheckMarkAtStart()); final TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs, CHECKED_TEXT_VIEW_ATTRS, defStyle, 0); final boolean checked = a.getBoolean(0, false); setChecked(checked); final Drawable d = a.getDrawable(1); if (d != null) { setCheckMarkDrawable(d); } a.recycle(); mTintManager = a.getTintManager(); } public void toggle() { setChecked(!mChecked); } public boolean isChecked() { return mChecked; } /** * <p>Changes the checked state of this text view.</p> * * @param checked true to check the text, false to uncheck it */ public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; refreshDrawableState(); } } /** * Set the checkmark to a given Drawable, identified by its resourece id. This will be drawn * when {@link #isChecked()} is true. * * @param resid The Drawable to use for the checkmark. */ public void setCheckMarkDrawable(int resid) { if (resid != 0 && resid == mCheckMarkResource) { return; } mCheckMarkResource = resid; setCheckMarkDrawable(mTintManager.getDrawable(resid)); } /** * Set the checkmark to a given Drawable. This will be drawn when {@link #isChecked()} is true. * * @param d The Drawable to use for the checkmark. */ public void setCheckMarkDrawable(Drawable d) { if (mCheckMarkDrawable != null) { mCheckMarkDrawable.setCallback(null); unscheduleDrawable(mCheckMarkDrawable); } if (d != null) { d.setCallback(this); d.setVisible(getVisibility() == VISIBLE, false); d.setState(CHECKED_STATE_SET); setMinHeight(d.getIntrinsicHeight()); mCheckMarkWidth = d.getIntrinsicWidth(); d.setState(getDrawableState()); } else { mCheckMarkWidth = 0; } mCheckMarkDrawable = d; updatePadding(); } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); if (mCheckMarkDrawable != null) { mCheckMarkDrawable.setVisible(visibility == VISIBLE, false); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if (mCheckMarkDrawable != null) { mCheckMarkDrawable.jumpToCurrentState(); } } @Override protected boolean verifyDrawable(Drawable who) { return who == mCheckMarkDrawable || super.verifyDrawable(who); } /** * Gets the checkmark drawable * * @return The drawable use to represent the checkmark, if any. * @attr ref android.R.styleable#CheckedTextView_checkMark * @see #setCheckMarkDrawable(Drawable) * @see #setCheckMarkDrawable(int) */ public Drawable getCheckMarkDrawable() { return mCheckMarkDrawable; } @Override public void setPadding(int left, int top, int right, int bottom) { super.setPadding(left, top, right, bottom); setBasePadding(isCheckMarkAtStart()); updatePadding(); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void setPaddingRelative(int start, int top, int end, int bottom) { super.setPaddingRelative(start, top, end, bottom); setBasePadding(isCheckMarkAtStart()); updatePadding(); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @Override public void onRtlPropertiesChanged(int layoutDirection) { super.onRtlPropertiesChanged(layoutDirection); invokeResetPaddingToInitialValues(); setBasePadding(isCheckMarkAtStart()); updatePadding(); } private void updatePadding() { int newPadding = (mCheckMarkDrawable != null) ? mCheckMarkWidth + mBasePadding : mBasePadding; if (isCheckMarkAtStart()) { mNeedRequestlayout |= (getPaddingLeftField() != newPadding); setPaddingLeftField(newPadding); } else { mNeedRequestlayout |= (getPaddingRightField() != newPadding); setPaddingRightFeild(newPadding); } if (mNeedRequestlayout) { requestLayout(); mNeedRequestlayout = false; } } private void setBasePadding(boolean checkmarkAtStart) { if (checkmarkAtStart) { mBasePadding = getPaddingLeftField(); } else { mBasePadding = getPaddingRightField(); } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) private boolean isCheckMarkAtStart() { boolean isCheckMarkAtStart = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { isCheckMarkAtStart = getLayoutDirection() == LAYOUT_DIRECTION_LTR; } return isCheckMarkAtStart; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); final Drawable checkMarkDrawable = mCheckMarkDrawable; if (checkMarkDrawable != null) { final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; final int height = checkMarkDrawable.getIntrinsicHeight(); int y = 0; switch (verticalGravity) { case Gravity.BOTTOM: y = getHeight() - height; break; case Gravity.CENTER_VERTICAL: y = (getHeight() - height) / 2; break; } final boolean checkMarkAtStart = isCheckMarkAtStart(); final int width = getWidth(); final int top = y; final int bottom = top + height; final int left; final int right; if (checkMarkAtStart) { left = mBasePadding; right = left + mCheckMarkWidth; } else { right = width - mBasePadding; left = right - mCheckMarkWidth; } checkMarkDrawable.setBounds(getScrollX() + left, top, getScrollX() + right, bottom); checkMarkDrawable.draw(canvas); checkMarkDrawable.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 (mCheckMarkDrawable != null) { int[] myDrawableState = getDrawableState(); // Set the state of the Drawable mCheckMarkDrawable.setState(myDrawableState); invalidate(); } } @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { boolean populated = super.dispatchPopulateAccessibilityEvent(event); if (!populated) { event.setChecked(mChecked); } return populated; } private void invokeResetPaddingToInitialValues() { try { Method resetPaddingToInitialValues = View.class.getDeclaredMethod("resetPaddingToInitialValues"); try { resetPaddingToInitialValues.invoke(this); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } private void ensurePaddingLeftField() { if (mPaddingLeftFeild == null) { try { mPaddingLeftFeild = View.class.getDeclaredField("mPaddingLeft"); } catch (NoSuchFieldException e) { e.printStackTrace(); } } } private int getPaddingLeftField() { ensurePaddingLeftField(); try { return mPaddingLeftFeild.getInt(this); } catch (IllegalAccessException e) { e.printStackTrace(); } return 0; } private void setPaddingLeftField(int paddingLeft) { ensurePaddingLeftField(); try { mPaddingLeftFeild.setInt(this, paddingLeft); } catch (IllegalAccessException e) { e.printStackTrace(); } } private void ensurePaddingRightField() { if (mPaddingRightFeild == null) { try { mPaddingRightFeild = View.class.getDeclaredField("mPaddingRight"); } catch (NoSuchFieldException e) { e.printStackTrace(); } } } private int getPaddingRightField() { ensurePaddingRightField(); try { return mPaddingRightFeild.getInt(this); } catch (IllegalAccessException e) { e.printStackTrace(); } return 0; } private void setPaddingRightFeild(int paddingRight) { ensurePaddingRightField(); try { mPaddingRightFeild.setInt(this, paddingRight); } catch (IllegalAccessException e) { e.printStackTrace(); } } }