zoukankan      html  css  js  c++  java
  • Android之自定义(上方标题随ViewPager手势慢慢滑动)

    最近很蛋疼,项目要模仿网易新闻的样式去做。上次把仿网易新闻客户端的下拉刷新写出来了,这次是ViewPager的滑动,同时ViewPager的上面标题下划线跟随者移动,本来通过ViewPager的OnPagerChangeListener的监听事件就可以完成,但是做出来之后,因为需要一直的刷新,所以很卡,一气之下,呵呵,自己完全的画了。整个点击事件,滑动事件都自己处理了。
    效果图如下:
     
     
    下标的长宽是随之改变的。
    使用方式:
    我的布局文件:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
     
     
        <com.flyme.columnhorizontalscrollview.ColumnHorizontalScrollView 
            android:layout_width="match_parent"
            android:paddingLeft="20dip"
            android:paddingRight="20dip"
            android:layout_height="100dip"
            android:id="@+id/title"
            />
        
        <android.support.v4.view.ViewPager
            android:background="@android:color/holo_orange_light"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/viewpager"
            />
        
    </LinearLayout>  
    很简单,把自定义的布局放在ViewPager的上面,很随意了,你想放哪就放哪。
     
    在Activity中的使用方式为:
     
    ViewPager mViewPager = (ViewPager) findViewById(R.id.viewpager);
            ColumnHorizontalScrollView title = (ColumnHorizontalScrollView) findViewById(R.id.title);
            mViewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
                @Override
                public int getCount() {
                    return 10;
                }
                
                @Override
                public Fragment getItem(int arg0) {
                    return new MyFragment(arg0);
                }
            });
            title.setTitle("上市的公司","历史","游戏啊","房产证","精选的搞笑片段","段子","电脑硬件","热点","轻松一刻","时尚");  //这个是设置标题的  
     
            title.setspace(40);
            title.setViewPager(mViewPager);  //这个是将ViewPager对象给自定义的View
     
    我就把自定义的类代码贴出来吧:比较懒了,时间比较紧,代码封装的不好,也没怎么封装,见谅。
    public class ColumnHorizontalScrollView extends View implements OnPageChangeListener {
     
        private Context context;
        private int width ;
        private int padingLeft;
        private int padingRight ; 
        private float lineStartX = 0  ;
        private float lineEndX = 0  ;
        private Paint textPaint;
        private int textWidth ;
        private int lastPosition = 0 ;
        private float lineScale = 0 ; 
        
        private ViewPager mViewPager ;
        
        
        /**
         * 这些事默认设置的
         */
        private static final int DEFULT_TEXT_COLOR = Color.BLACK;
        private static final int DEFULT_TEXT_SIZE = 40;
        private  static final int DEFULT_LINE_COLOR = Color.RED;
        private static final int DEFULT_LINE_STRO = 5;
        
        
        private String [] str ; // 存储 题要显示的字符
        private float [] strX ; // 存储 每个字符  开始的X位置
        private float [] strWidth ;  // 存储每个字符的长度
        private int startX; // 与手势相关    记录按下的X的坐标
        
        private int recordDownX = 0 ;
        
        private OnClickOneListener mOnClickOneListener ;
        private OverScroller mScroller; 
     
        public ColumnHorizontalScrollView(Context context, AttributeSet attrs,
                int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
        
        public ColumnHorizontalScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
        public ColumnHorizontalScrollView(Context context) {
            super(context);
            init(context);
        }
        
        
        /**
         * 初始化的时候需要new出来的一些类,和必要的设置
         * @param context
         */
        private void init(Context context){
            this.context = context ;
            mScroller = new OverScroller(context,new LinearInterpolator());
            textPaint = new Paint();
            linePaint = new Paint();
            
            textPaint.setColor(DEFULT_TEXT_COLOR);
            textPaint.setTextSize(DEFULT_TEXT_SIZE);
            textPaint.setTypeface(Typeface.SANS_SERIF);
            
            linePaint.setColor(DEFULT_LINE_COLOR);
            linePaint.setStrokeWidth(DEFULT_LINE_STRO);
        }
        
        
        
        
        /**
         * 画图
         */
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (str == null) {
                return ;
            }
            measureSize();
            drawText(canvas); //画字
            measureLineSize();//测量下划线的位置
            drawLine(canvas);//画下划线
        }
        
        
        
        /**
         * 这个是用来通过Scroller来控制缓冲变化的   后来不需要了
         */
        @Override
        public void computeScroll() {
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            }
            super.computeScroll();
            postInvalidate();
        }
        
        
        /**
         * 画字的具体代码
         * @param canvas
         */
        private  void drawText(Canvas canvas){
            int totel = 0 ;
            for (int i = 0; i < str.length; i++) {
                if (i == 0 ) {
                    totel += padingLeft;
                }
                strX[i] = totel ;
                canvas.drawText(str[i], strX[i], textHeight, textPaint);
                float oneTextWidth = textPaint.measureText(str[i]);
                totel =(int) (totel +  oneTextWidth +space);
                strWidth[i] = oneTextWidth ;
            }
            textWidth = totel - space  +padingLeft ;
        }
        
        
        private void drawLine(Canvas canvas){
            canvas.drawLine(lineStartX, lineHeight ,lineEndX , lineHeight, linePaint);
        }
        
        
        
        private void measureSize(){
            width = getWidth();
            height = getHeight();
            padingLeft = getPaddingLeft();
            padingRight = getPaddingRight();
            textHeight = (int) (height / 2 - (textPaint.descent() + textPaint.ascent())/2); 
            lineHeight = (int) (textHeight - (textPaint.descent() + textPaint.ascent()));
        }
        
        
        
        private void measureLineSize(){
            lineStartX = strX[lastPosition] - space / 2 + (strWidth[lastPosition] + space )* lineScale;
            if ((lastPosition + 1) == mViewPager.getAdapter().getCount()) {
                lineEndX = strX[lastPosition] + strWidth[lastPosition] + space / 2 ;          
            }else {
                lineEndX = strX[lastPosition] + strWidth[lastPosition] + space / 2 + ( strWidth[lastPosition + 1] + space ) * lineScale;          
            }
        }
        
        
        
        public void setTitle(String ...str){
            this.str = str ;
            strX = new float[str.length];
            strWidth = new float[str.length];
        }
        
        
        private int space = 0 ;
        private Paint linePaint;
        private int lineHeight;
        private int height;
        private int textHeight;
        
        public void setspace(int space){
            this.space = space ;
        }
        
        public void setTextColorResourceId(int colorid){
            int color = context.getResources().getColor(colorid);
            textPaint.setColor(color);
        }
        
        public void setTextColor(int color){
            textPaint.setColor(color);
        }
        
        
        
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = recordDownX = (int) event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) event.getX();
                int scrollX = getScrollX();
                if (Math.abs(moveX - recordDownX ) > 32 ) {
                    smootMove(scrollX , startX - moveX);
                }
                startX = (int) event.getX();
                break;
            case MotionEvent.ACTION_UP:
                int upX = (int) event.getX();
                if (Math.abs(upX - recordDownX ) < 32 ) {
                    int position = decidePosition(upX);
                    setPosition(position);
                    if (mOnClickOneListener != null) {
                        mOnClickOneListener.onClick(position) ;
                    }
                }
                break;
            }
            return true;
        }
        
        
        private int  decidePosition(int upX){
            for (int i = 0; i < strX.length; i++) {
                if ((upX + getScrollX()) < (strX[i] + strWidth[i]) + space / 2) {
                    return i ;
                }
            }
            return 0 ;
        }
        
        
        public void setPosition(int position){
    //        lastPosition = position ;
    //        int scrollX = getScrollX();
    //        int location = (int) (strX[lastPosition] - space - 20);
    //        int dy = (int)(location  - getScrollX());
    //        if ((location + width) > (textWidth + padingRight ) ) {
    //            mScroller.startScroll(scrollX, 0,textWidth + padingRight - width - getScrollX()  , 0, 200);
    //        }else {
    //            mScroller.startScroll(scrollX, 0, dy , 0, 200);
    //        }
    //        if ((scrollX + dy ) > (textWidth+padingRight - width)) {
    //            mScroller.startScroll(scrollX, 0, textWidth+padingRight - width - scrollX , 0, 200);
    //        }else {
    //            mScroller.startScroll(scrollX, 0, dy , 0, 200);
    //        }
            mViewPager.setCurrentItem(position);
        }
        
        
        private void smootMove(int scrollX , int dy){
            if ((scrollX <= 0 && dy > 0 && textWidth > width)  || (scrollX > 0)) {
                if ((scrollX + dy) < 0 ) {
                    scrollTo(0 , 0);
                }else {
                    if ((scrollX + dy + getWidth()) > (textWidth+padingRight )) {
                        scrollTo(textWidth +padingRight - getWidth() , 0);
                    }else {
                        scrollTo(scrollX + dy , 0);
                    }
                }
            }
        }
        
        public void setViewPager(ViewPager mViewPager){
            this.mViewPager = mViewPager;
            if (this.mViewPager != null) {
                this.mViewPager.setOnPageChangeListener(this);
            }
        }
        
        /**
         * dip转为 px
         */
        public int dip2px(float dipValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dipValue * scale + 0.5f);
        }
     
        @Override
        public void onPageScrollStateChanged(int arg0) {
            
        }
     
        @Override
        public void onPageScrolled(int lastPosition, float scale, int location) {
            this.lastPosition = lastPosition ;
            lineScale = scale ;
            invalidate();
            smootMove((int)(strX[lastPosition] - space - 20 ) ,(int)((strWidth[lastPosition] + space )*  lineScale));
        }
     
        @Override
        public void onPageSelected(int arg0) {
        }
        
        
        public void setOnClickOneListener (OnClickOneListener mOnClickOneListener){
            this.mOnClickOneListener = mOnClickOneListener ;
        }
        
        
        /**
         * 内部接口    是点击事件的接口
         * @author lenovo
         *
         */
        interface OnClickOneListener{
            public void onClick(int position);
        }
        
    }  
     
    over。
    关于bug:
    这个做的还不是很完善,还有一些东西没有做适配。如果有人用,在使用过程中出现问题,你可以自己做一下简单的适配。
     
     
    源码下载地址: 

    http://pan.baidu.com/s/1sj0lIxR


     
    我的github地址:https://github.com/flyme2012
    我的博客地址:http://www.cnblogs.com/flyme2012/
  • 相关阅读:
    MySQL全文索引应用简明教程
    web前端的春天 or 噩梦
    [DeviceOne开发]-手势动画示例分享
    [DeviceOne开发]-土地销售项目源码分享
    [DeviceOne开发]-do_LinearLayout组件使用技巧
    2016年我们重新思考移动互联网创业的风险, 微信还是APP?
    APP技术演化的路
    ReactNative&weex&DeviceOne对比
    what's deviceone
    APP开放源码第一弹《纳豆》
  • 原文地址:https://www.cnblogs.com/flyme2012/p/4092895.html
Copyright © 2011-2022 走看看