ColorTrackView

원문http://blog.csdn.net/lmj623565791/article/details/44098729
이것 은 텍스트 높이 의 동적 효과 도 추 가 했 습 니 다.https://github.com/hongyangAndroid/ColorTrackView/blob/master/library_ColorTrackView/src/com/zhy/view/ColorTrackView.java https://github.com/hongyangAndroid/ColorTrackView
//사용자 정의 속성
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="text" format="string" />
    <attr name="text_size" format="dimension" />
    <attr name="text_origin_color" format="color|reference" />
    <attr name="text_change_color" format="color|reference" />
    <attr name="progress" format="float" />
    <attr name="direction">
        <enum name="left" value="0" />
        <enum name="right" value="1" />
    </attr>

    <declare-styleable name="ColorTrackView">
        <attr name="text" />
        <attr name="text_size" />
        <attr name="text_origin_color" />
        <attr name="text_change_color" />
        <attr name="progress" />
        <attr name="direction" />
    </declare-styleable>

</resources>

//사용자 정의 Tab 클래스
public class ColorTrackView extends View {

    private int mTextStartX;

    public enum Direction {
        LEFT, RIGHT;
    }

    private int mDirection = DIRECTION_LEFT;

    private static final int DIRECTION_LEFT = 0;
    private static final int DIRECTION_RIGHT = 1;

    public void setDirection(int direction) {
        mDirection = direction;
    }

    private String mText = "default String";
    private Paint mPaint;
    // private int mTextSize = sp2px(30);
    private int mTextSize = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP, 30, getResources().getDisplayMetrics());

    private int mTextOriginColor = 0xff000000;
    private int mTextChangeColor = 0xffff0000;

    private Rect mTextBound = new Rect();
    private int mTextWidth;

    private int mRealWidth;

    private float mProgress;

    public ColorTrackView(Context context) {
        this(context, null);
    }

    public ColorTrackView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        TypedArray ta = context.obtainStyledAttributes(attrs,
                R.styleable.ColorTrackView);
        mText = ta.getString(R.styleable.ColorTrackView_text);
        mTextSize = ta.getDimensionPixelSize(
                R.styleable.ColorTrackView_text_size, mTextSize);
        mTextOriginColor = ta.getColor(
                R.styleable.ColorTrackView_text_origin_color, mTextOriginColor);
        mTextChangeColor = ta.getColor(
                R.styleable.ColorTrackView_text_change_color, mTextChangeColor);
        mProgress = ta.getFloat(R.styleable.ColorTrackView_progress, 0);

        mDirection = ta
                .getInt(R.styleable.ColorTrackView_direction, mDirection);

        ta.recycle();

        mPaint.setTextSize(mTextSize);
        measureText();
    }

    private void measureText() {
        mTextWidth = (int) mPaint.measureText(mText);
        mPaint.getTextBounds(mText, 0, mText.length(), mTextBound); //    mTextBound
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);

        setMeasuredDimension(width, height);

        mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); //      
        mTextStartX = mRealWidth / 2 - mTextWidth / 2;  //           ,       

    }

    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int val = MeasureSpec.getSize(heightMeasureSpec);
        int result = 0;
        switch (mode) {
        case MeasureSpec.EXACTLY:
            result = val;
            break;

        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            result = mTextBound.height();
            break;
        }
        result = mode == MeasureSpec.AT_MOST ? Math.min(result, val) : result;
        return result + getPaddingTop() + getPaddingBottom();
    }

    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int val = MeasureSpec.getSize(widthMeasureSpec);
        int result = 0;
        switch (mode) {
        case MeasureSpec.EXACTLY:
            result = val;
            break;
        case MeasureSpec.AT_MOST:
        case MeasureSpec.UNSPECIFIED:
            result = mTextWidth;
            break;
        }
        result = mode == MeasureSpec.AT_MOST ? Math.min(result, val) : result;
        return result + getPaddingLeft() + getPaddingRight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e("TAG","mTextStartX"+ mTextStartX);

        // mTextStartX         ,   mProgress * mTextWidth       
        //      mTextStartX +          ,                   ,    r 
        //   ,           ,        r ,      , mProgress     , 
        //     drawOriginRight(canvas, r); drawChangeRight(canvas, r); 
        //    r     ...           ,            


        int r = (int) (mProgress * mTextWidth + mTextStartX);

        Log.e("TAG","mProgress * mTextWidth + mTextStartX"+ r);


        //                  mDirection left
        if (mDirection == DIRECTION_LEFT) {
            drawChangeLeft(canvas, r);
            drawOriginLeft(canvas, r);
        } else { 

            //      ,            ,       
            drawOriginRight(canvas, r);
            drawChangeRight(canvas, r);
        }
    }


    //   save, restore          ??
    //      

    private void drawText(Canvas canvas, int color, int startX, int endX) {
        mPaint.setColor(color);
        canvas.save(Canvas.CLIP_SAVE_FLAG);
        canvas.clipRect(startX, 0, endX, getMeasuredHeight()); //             
        canvas.drawText(mText, mTextStartX, getMeasuredHeight() / 2
                + mTextBound.height() / 2, mPaint);
        canvas.restore();
    }

    /** *               r ,   progress           ,           *               mTextStartX + mTextWidth ,        +      * @param canvas * @param r */
    private void drawChangeRight(Canvas canvas, int r) {
        drawText(canvas, mTextChangeColor, (int) (mTextStartX + (1 - mProgress)
                * mTextWidth), mTextStartX + mTextWidth);
    }

    private void drawOriginRight(Canvas canvas, int r) {
        drawText(canvas, mTextOriginColor, mTextStartX,
                (int) (mTextStartX + (1 - mProgress) * mTextWidth));
    }

    private void drawOriginLeft(Canvas canvas, int r) {
        drawText(canvas, mTextOriginColor, (int) (mTextStartX + mProgress
                * mTextWidth), mTextStartX + mTextWidth);
    }

    //   mProgress  0 ,          
    //           ,            progress     1,         
    //  pager   , progress        0- 1   1-0
    private void drawChangeLeft(Canvas canvas, int r) {
        drawText(canvas, mTextChangeColor, mTextStartX,
                (int) (mTextStartX + mProgress * mTextWidth));

    }

    //  progress    
    public void setProgress(float progress) {
        this.mProgress = progress;
        invalidate();
    }

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

//Activity 테스트
public class MainActivity extends FragmentActivity {
    private String[] mTitles = new String[] { "  ", "  ", "  " };
    private ViewPager mViewPager;
    private FragmentPagerAdapter mAdapter;
    private TabFragment[] mFragments = new TabFragment[mTitles.length];
    private List<ColorTrackView> mTabs = new ArrayList<ColorTrackView>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();
        initDatas();
        initEvents();
    }

    private void initViews() {
        mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
        mTabs.add((ColorTrackView) findViewById(R.id.id_tab_01));
        mTabs.add((ColorTrackView) findViewById(R.id.id_tab_02));
        mTabs.add((ColorTrackView) findViewById(R.id.id_tab_03));
    }

    private void initDatas() {
        for (int i = 0; i < mTitles.length; i++) {
            mFragments[i] = TabFragment.newInstance(mTitles[i]);
        }

        mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {

            @Override
            public int getCount() {
                return mTitles.length;
            }

            @Override
            public Fragment getItem(int position) {
                return mFragments[position];
            }
        };

        mViewPager.setAdapter(mAdapter);
        mViewPager.setCurrentItem(0);
    }

    private void initEvents() {
        mViewPager.addOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageScrollStateChanged(int arg0) {

            }

            @Override
            public void onPageScrolled(int position, float positionOffset,
                    int positionOffsetPixels) {
                /** *       positionOffset > 0 ,   ,       ,              * position    positionOffset  0 ,   mTabs.get(position + 1)       ,      *     postion               , *     positionOffset    0,                      */

                if (positionOffset > 0)  {
                    ColorTrackView left = mTabs.get(position);
                    ColorTrackView right = mTabs.get(position + 1);

                    left.setDirection(1);
                    right.setDirection(0);
                    Log.e("TAG",position +"---"+ positionOffset + "");

                    /*** *         positionOffset 0-1 *       positionOffset 1-0 */

                    left.setProgress(1 - positionOffset);    // ->  progress 1-0 ,             
                    right.setProgress(positionOffset);   // ->  progress 0-1 ,             
                }

            }

            @Override
            public void onPageSelected(int arg0) {

            }

        });
    }

}

//ViewPager 를 구성 하 는 Fragment
public class TabFragment extends Fragment {
    public static final String TITLE = "title";
    private String mTitle = "Default Title";


    /** *   Activity        */
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(getArguments() != null){
            mTitle = getArguments().getString(TITLE);
        }
    }

    /** * Fragment        ,        view */

    @Override
    @Nullable
    public View onCreateView(LayoutInflater inflater,
            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //    TextView ,     ,     
        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;
    }

}

좋은 웹페이지 즐겨찾기