Android 自定义变化的文本控件ColorChangeView

来源:互联网 发布:淘宝网披肩女装 编辑:程序博客网 时间:2024/05/22 13:08

实例图
这里写图片描述

说明图
这里写图片描述

/** * 有颜色过渡变化的textview *  * @Project App_View * @Package com.android.view.colortextview * @author chenlin * @version 1.0 * @Note TODO *//** * 有颜色过渡变化的textview *  * @Project App_View * @Package com.android.view.colortextview * @author chenlin * @version 1.0 * @Note TODO */public class ColorChangeView extends View {    public static final int DIRECTION_LEFT = 0;    public static final int DIRECTION_RIGHT = 1;    public static final int DIRECTION_TOP = 2;    public static final int DIRECTION_BOTTOM = 3;    public static final String DEFAULT_TEXT = "颜色变化";    // 默认字体大小    private static final int DEF_TEXT_SIZE = 0;    // 文本内容    private String mText;    // 文本大小    private int mTextSize = sp2px(30);    // 文本原来颜色    private int mOriginColor = 0xff000000;    // 文本改变后的颜色    private int mChangeColor = 0xffff0000;    // 改变颜色时的进度百分比    private float mProgress;    // 改变颜色的方向,默认从左边开始变色    private int mDirection = DIRECTION_LEFT;    // 绘制文本的画笔    private Paint mPaint;    // ---测量信息----------------------------------------    // 文本宽度    private int mTextWidth;    // 文本高度    private int mTextHeight;    // 文本区域    private Rect mTextBound = new Rect();    // 开始移动坐标    private int mTextStartX;    private int mTextStartY;    /** 总共分四个方向 */    public enum Direction {        LEFT, RIGHT, TOP, BOTTOM;    }    public ColorChangeView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context, attrs);    }    public ColorChangeView(Context context) {        this(context, null);    }    private void init(Context context, AttributeSet attrs) {        // 初始化画笔        mPaint = new Paint();        mPaint.setAntiAlias(true);        // 初始化自定义属性        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColorChangeView);        mText = ta.getString(R.styleable.ColorChangeView_text);        mTextSize = ta.getDimensionPixelSize(R.styleable.ColorChangeView_text_size, mTextSize);        mOriginColor = ta.getColor(R.styleable.ColorChangeView_text_origin_color, mOriginColor);        mChangeColor = ta.getColor(R.styleable.ColorChangeView_text_change_color, mChangeColor);        mProgress = ta.getFloat(R.styleable.ColorChangeView_progress, 0);        mDirection = ta.getInt(R.styleable.ColorChangeView_direction, mDirection);        ta.recycle();        // 为画笔设置文本大小        mPaint.setTextSize(mTextSize);    }    /**     * 测量     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // 第一步:先测量文本的区域大小        measureText();        // 第二步:对视图测量        int width = measureWidth(widthMeasureSpec);        int height = measureHeight(heightMeasureSpec);        // 这个方法决定了当前View的大小        setMeasuredDimension(width, height);        // 从有文字的位置开始绘制        mTextStartX = (getMeasuredWidth() - mTextWidth) / 2;        mTextStartY = (getMeasuredHeight() - mTextHeight) / 2;    }    /**     * 测量高度     *      * @param heightMeasureSpec     * @return     */    private int measureHeight(int heightMeasureSpec) {        int height = 0;        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        switch (heightMode) {        case MeasureSpec.EXACTLY:            height = heightSize;            break;        case MeasureSpec.AT_MOST:        case MeasureSpec.UNSPECIFIED:            height = mTextBound.height();            height += getPaddingBottom() + getPaddingTop();            break;        }        return height = heightMode == MeasureSpec.AT_MOST ? Math.min(height, heightSize) : height;    }    /**     * 测量宽度     *      * @param widthMeasureSpec     * @return     */    private int measureWidth(int widthMeasureSpec) {        int width = 0;        int widthtSize = MeasureSpec.getSize(widthMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        switch (widthMode) {        case MeasureSpec.EXACTLY:            width = widthtSize;            break;        case MeasureSpec.AT_MOST:        case MeasureSpec.UNSPECIFIED:            width = mTextWidth;            width += getPaddingLeft() + getPaddingRight();            break;        }        return width = widthMode == MeasureSpec.AT_MOST ? Math.min(width, widthtSize) : width;    }    /**     * 对文本控件测量,得到绘制时的宽高     */    private void measureText() {        mTextWidth = (int) mPaint.measureText(mText);        FontMetrics fm = mPaint.getFontMetrics();        // 文本的最低处-文本的最高处        mTextHeight = (int) Math.ceil(fm.descent - fm.top);        mPaint.getTextBounds(mText, 0, mText.length(), mTextBound);        // 获得高度        mTextHeight = mTextBound.height();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // 水平移动距离        int distance_x = (int) (mProgress * mTextWidth + mTextStartX);        // 垂直移动距离        int distance_y = (int) (mProgress * mTextHeight + mTextStartY);        // 从左移动        if (mDirection == DIRECTION_LEFT) {            drawOriginLeft(canvas, distance_x);            drawChangeLeft(canvas, distance_x);            // 从右移动        } else if (mDirection == DIRECTION_RIGHT) {            drawOriginRight(canvas, distance_x);            drawChangeRight(canvas, distance_x);            // 从上移动        } else if (mDirection == DIRECTION_TOP) {            drawOriginTop(canvas, distance_y);            drawChangeTop(canvas, distance_y);        } else if (mDirection == DIRECTION_BOTTOM) {            // 从底部移动            drawOriginBottom(canvas, distance_y);            drawChangeBottom(canvas, distance_y);        }    }    /**     * 反转颜色     */    public void reverseColor() {        int tmp = mOriginColor;        mOriginColor = mChangeColor;        mChangeColor = tmp;    }    /**     * 从左绘制变化的文本     *      * @param canvas     * @param hProgress     */    private void drawChangeLeft(Canvas canvas, int distance_x) {        drawText_x(canvas, mChangeColor, mTextStartX, distance_x);    }    /**     * 从左绘制原来的文本     *      * @param canvas     * @param hProgress     */    private void drawOriginLeft(Canvas canvas, int distance_x) {        drawText_x(canvas, mOriginColor, distance_x, mTextStartX + mTextWidth);    }    /**     * 从右边绘制原文本     *      * @param canvas     * @param distance_x     */    private void drawOriginRight(Canvas canvas, int distance_x) {        drawText_x(canvas, mOriginColor, (int) (mTextStartX + (1 - mProgress) * mTextWidth), mTextStartX + mTextWidth);    }    /**     * 从右边绘制变化文本     *      * @param canvas     * @param distance_x     */    private void drawChangeRight(Canvas canvas, int distance_x) {        drawText_x(canvas, mChangeColor, mTextStartX, (int) (mTextStartX + (1 - mProgress) * mTextWidth));    }    private void drawOriginTop(Canvas canvas, int distance_y) {        drawText_y(canvas, mOriginColor, mTextStartY, (int) (mTextStartY + mProgress * mTextHeight));    }    private void drawChangeTop(Canvas canvas, int distance_y) {        drawText_y(canvas, mChangeColor, (int) (mTextStartY + mProgress * mTextHeight), mTextStartY + mTextHeight);    }    private void drawChangeBottom(Canvas canvas, int distance_y) {        drawText_y(canvas, mChangeColor, (int) (mTextStartY + (1 - mProgress) * mTextHeight), mTextStartY + mTextHeight);    }    private void drawOriginBottom(Canvas canvas, int distance_y) {        drawText_y(canvas, mOriginColor, mTextStartY, (int) (mTextStartY + (1 - mProgress) * mTextHeight));    }    private boolean debug = false;    /**     * 水平绘制     *      * @param canvas     * @param color     * @param startX     * @param endX     */    private void drawText_x(Canvas canvas, int color, int startX, int endX) {        mPaint.setColor(color);        if (debug) {            mPaint.setStyle(Style.STROKE);            // 第一步:先绘制矩形区域,在这之前,设定画笔的颜色            canvas.drawRect(startX, 0, endX, getMeasuredHeight(), mPaint);        }        canvas.save(Canvas.CLIP_SAVE_FLAG);        // 第二步:实现动画绘制,在之前,先保存绘制好的区域        canvas.clipRect(startX, 0, endX, getMeasuredHeight());        // 第三步:绘制出整个文本, mPaint.descent() + mPaint.ascent() = 字体的高 getMeasuredHeight是view的高        canvas.drawText(mText, mTextStartX, getMeasuredHeight() / 2 - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint);        // 第四步:恢复画布        canvas.restore();    }    /**     * 垂直绘制     *      * @param canvas     * @param color     * @param startY     * @param endY     */    private void drawText_y(Canvas canvas, int color, int startY, int endY) {        mPaint.setColor(color);        if (debug) {            mPaint.setStyle(Style.STROKE);            // 第一步:先绘制矩形区域,在这之前,设定画笔的颜色            canvas.drawRect(0, startY, getMeasuredWidth(), endY, mPaint);        }        canvas.save(Canvas.CLIP_SAVE_FLAG);        // 第二步:实现动画绘制,在之前,先保存绘制好的区域        canvas.clipRect(0, startY, getMeasuredWidth(), endY);        // 第三步:绘制出整个文本, mPaint.descent() + mPaint.ascent() = 字体的高 getMeasuredHeight是view的高        canvas.drawText(mText, mTextStartX, getMeasuredHeight() / 2 - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint);        // 第四步:恢复画布        canvas.restore();    }    // --Set Get --向外提供的方法--------------------------------------------------------    public void setDirection(int direction) {        this.mDirection = direction;    }    public float getProgress() {        return mProgress;    }    public void setProgress(float progress) {        this.mProgress = progress;        invalidate();    }    public int getTextSize() {        return mTextSize;    }    public void setTextSize(int textSize) {        this.mTextSize = textSize;        mPaint.setTextSize(mTextSize);        requestLayout();        invalidate();    }    public void setText(String text) {        this.mText = text;        requestLayout();        invalidate();    }    public int getTextOriginColor() {        return mOriginColor;    }    public void setTextOriginColor(int originColor) {        this.mOriginColor = originColor;        invalidate();    }    public int getTextChangeColor() {        return mChangeColor;    }    public void setTextChangeColor(int changeColor) {        this.mChangeColor = changeColor;        invalidate();    }    // ---像素转化函数----------------------------------------------------    public int dp2px(float dpVal) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics());    }    public int sp2px(float dpVal) {        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dpVal, getResources().getDisplayMetrics());    }    // ----保存和恢复数据-----------------------------------------------------------------    private static final String KEY_STATE_PROGRESS = "key_progress";    private static final String KEY_DEFAULT_STATE = "key_default_state";    @Override    protected Parcelable onSaveInstanceState() {        Bundle bundle = new Bundle();        bundle.putFloat(KEY_STATE_PROGRESS, mProgress);        bundle.putParcelable(KEY_DEFAULT_STATE, super.onSaveInstanceState());        return bundle;    }    @Override    protected void onRestoreInstanceState(Parcelable state) {        if (state instanceof Bundle) {            Bundle bundle = (Bundle) state;            mProgress = bundle.getFloat(KEY_STATE_PROGRESS);            super.onRestoreInstanceState(bundle.getParcelable(KEY_DEFAULT_STATE));            return;        }        super.onRestoreInstanceState(state);    }}

运用

public class HomeActivity extends ListActivity {    private String[] mTitles = new String[] { "简单使用", "变化应用" };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        getListView().setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mTitles));    }    @Override    protected void onListItemClick(ListView l, View v, int position, long id) {        Intent intent = null;        switch (position) {        case 0:            intent = new Intent(this,SimpleActivity.class);            break;        case 1:            intent = new Intent(this,ViewPagerActivity.class);            break;        }        if (intent != null) {            startActivity(intent);        }    }}

1)简单运用

public class SimpleActivity extends Activity implements OnClickListener {    @ViewInject(R.id.id_changeTextColorView)    private ColorChangeView mView;    @ViewInject(R.id.id_left)    private Button mBtnLeft;    @ViewInject(R.id.id_right)    private Button mBtnRight;    @ViewInject(R.id.id_top)    private Button mBtnTop;    @ViewInject(R.id.id_bottom)    private Button mBtnBottom;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_simpepager);        ViewUtils.inject(this);        initEvents();    }    private void initEvents() {        mBtnLeft.setOnClickListener(this);        mBtnRight.setOnClickListener(this);        mBtnTop.setOnClickListener(this);        mBtnBottom.setOnClickListener(this);    }    @Override    public void onClick(View v) {        if (v == mBtnLeft) {            mView.setDirection(ColorChangeView.DIRECTION_LEFT);            ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start();        }else if (v == mBtnRight) {            mView.setDirection(ColorChangeView.DIRECTION_RIGHT);            ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start();        }else if (v == mBtnTop) {            mView.setDirection(ColorChangeView.DIRECTION_TOP);            ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start();        }else if (v == mBtnBottom) {            mView.setDirection(ColorChangeView.DIRECTION_BOTTOM);            ObjectAnimator.ofFloat(mView, "progress", 0,1).setDuration(2000).start();        }    }}

布局

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:koo="http://schemas.android.com/apk/res/com.android.view"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <com.android.view.colortextview.ColorChangeView        android:id="@+id/id_changeTextColorView"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:background="#44ff0000"        android:padding="10dp"        koo:progress="0"        koo:text="北京我来了"        koo:text_change_color="#ffff0000"        koo:text_origin_color="#ff000000"        koo:text_size="60sp" />    <LinearLayout        android:id="@+id/ll"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:gravity="center"        android:orientation="horizontal" >        <Button            android:id="@+id/id_left"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="startLeft" />        <Button             android:id="@+id/id_right"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_toRightOf="@id/id_left"            android:text="startRight" />    </LinearLayout>     <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_alignParentBottom="true"         android:layout_alignParentLeft="true"         android:layout_marginBottom="45dp"         android:layout_above="@id/ll"         android:gravity="center"         android:orientation="horizontal" >         <Button             android:id="@+id/id_top"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:text="startTop" />         <Button             android:id="@+id/id_bottom"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             android:layout_toRightOf="@id/id_left"             android:text="startBottom" />     </LinearLayout></RelativeLayout>

2)使用viewpager展示

public class ViewPagerActivity extends FragmentActivity {    private String[] mTitles = new String[] { "简介", "评价", "相关" };      //创建viewpager    private ViewPager mViewPager;    //定义数据数组    private TabFragment[] mDatas = new TabFragment[mTitles.length];    //定义标题控件    private List<ColorChangeView> mTabs = new ArrayList<ColorChangeView>();    private FragmentPagerAdapter mAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_viewpager);        initViews();        initDatas();        initEvenvts();    }    private void initViews() {        mViewPager = (ViewPager) findViewById(R.id.id_viewpager);        mTabs.add((ColorChangeView) findViewById(R.id.id_tab_01));        mTabs.add((ColorChangeView) findViewById(R.id.id_tab_02));        mTabs.add((ColorChangeView) findViewById(R.id.id_tab_03));    }    private void initDatas() {        for (int i = 0; i < mTitles.length; i++) {            mDatas[i] = TabFragment.newInstance(mTitles[i]);        }        mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()){            @Override            public Fragment getItem(int position) {                return mDatas[position];            }            @Override            public int getCount() {                return mTitles.length;            }        };        mViewPager.setAdapter(mAdapter);        mViewPager.setCurrentItem(0);    }    private void initEvenvts() {        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {            @Override            public void onPageSelected(int position) {            }            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {                if (positionOffset > 0) {                    ColorChangeView left = mTabs.get(position);                    left.setDirection(ColorChangeView.DIRECTION_LEFT);                    left.setProgress(1-positionOffset);                    ColorChangeView right = mTabs.get(position+1);                    right.setDirection(ColorChangeView.DIRECTION_RIGHT);                    right.setProgress(positionOffset);                }            }            @Override            public void onPageScrollStateChanged(int state) {            }        });    }}

Fragment代码

public class TabFragment extends Fragment {    public static final String TITLE = "title";    private String mTitle = "Defaut Value";    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (getArguments() != null) {            mTitle = getArguments().getString(TITLE);        }    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        TextView tv = new TextView(getActivity());        tv.setTextSize(60);        Random r = new Random();        tv.setBackgroundColor(Color.argb(r.nextInt(120), r.nextInt(255), r.nextInt(255), r.nextInt(255)));        tv.setText(mTitle);        tv.setGravity(Gravity.CENTER);        return tv;    }    public static TabFragment newInstance(String title) {        TabFragment tabFragment = new TabFragment();        Bundle bundle = new Bundle();        bundle.putString(TITLE, title);        //保存标题信息        tabFragment.setArguments(bundle);        return tabFragment;    }}

相关布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:koo="http://schemas.android.com/apk/res/com.android.view"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="50dp"        android:background="@color/state_menu_item_selected"        android:orientation="horizontal" >        <com.android.view.colortextview.ColorChangeView            android:id="@+id/id_tab_01"            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            koo:progress="1"            koo:text="简介"            koo:text_change_color="#ffff0000"            koo:text_origin_color="#ff000000"            koo:text_size="18sp" />        <com.android.view.colortextview.ColorChangeView            android:id="@+id/id_tab_02"            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            koo:text="评价"            koo:text_change_color="#ffff0000"            koo:text_origin_color="#ff000000"            koo:text_size="18sp" />        <com.android.view.colortextview.ColorChangeView            android:id="@+id/id_tab_03"            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            koo:text="相关"            koo:text_change_color="#ffff0000"            koo:text_origin_color="#ff000000"            koo:text_size="18sp" />    </LinearLayout>    <android.support.v4.view.ViewPager        android:id="@+id/id_viewpager"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1" >    </android.support.v4.view.ViewPager></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_pressed="true"          android:drawable="@android:color/holo_green_light"/> <!-- pressed -->    <item android:drawable="@android:color/holo_green_dark"/> <!-- default --></selector>
0 0
原创粉丝点击