Android Open Source - AlertDialogPro Checked Text View Compat






From Project

Back to project page AlertDialogPro.

License

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.

Java Source Code

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();
        }
    }
}




Java Source Code List

com.alertdialogpro.AlertDialogPro.java
com.alertdialogpro.ProgressDialogPro.java
com.alertdialogpro.demo.MainActivity.java
com.alertdialogpro.holo.internal.NoTintCheckedTextView.java
com.alertdialogpro.internal.AlertController.java
com.alertdialogpro.internal.DialogTitle.java
com.alertdialogpro.material.ButtonCompat.java
com.alertdialogpro.material.CheckedTextViewCompat.java
com.alertdialogpro.material.ProgressBarCompat.java
com.alertdialogpro.material.drawable.CircularAnimatedDrawable.java