近期非常蛋疼,项目要模仿网易新闻的样式去做。上次把仿网易新闻client的下拉刷新写出来了。这次是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>

非常easy。把自己定义的布局放在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/

Android之自己定义(上方标题随ViewPager手势慢慢滑动)的更多相关文章

  1. Android之自定义(上方标题随ViewPager手势慢慢滑动)

    最近很蛋疼,项目要模仿网易新闻的样式去做.上次把仿网易新闻客户端的下拉刷新写出来了,这次是ViewPager的滑动,同时ViewPager的上面标题下划线跟随者移动,本来通过ViewPager的OnP ...

  2. Android典型界面设计(6)——ActionBar Tab+ViewPager+Fagment实现滑动导航

    一.问题描述 在Android典型界面设计一文中,实现典型滑动导航界面,其实使用ActionBar 也可以轻松实现这一效果,甚至也可实现类似Android典型界面设计(3)的双导航效果.可见Actio ...

  3. Android 向右滑动销毁(finish)Activity, 随着手势的滑动而滑动的效果

    http://blog.csdn.net/xiaanming/article/details/20934541

  4. 自定义ViewPager控制是否滑动

    package com.lvshandian.menshen.view;/** * Created by zhang on 2016/11/8. * 创建自定义滑动,禁止滑动的ViewPager */ ...

  5. Android peferenceActivity 自己定义标题简单方法

    Android peferenceActivity 自己定义标题简单方法 peferenceActivity 全然使用定义好的布局. 因此不能简单象其他好窗体进行自定,如今我们须要加 一个自己定义标题 ...

  6. 114、Android禁止ViewPager的左右滑动

    有时候在开发中会遇到一些“诡异”的要求,比如在ViewPager中嵌入ListView,或者再嵌入一个ViewPager,那么在滑动的时候就会造成被嵌入的XXView不能滑动了,那么现在就把最外层的V ...

  7. Android ViewPager多页面滑动切换以及动画效果

    一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式,白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了, ...

  8. android 很多应用中用到的 listView + viewPager

    比如网易啊啥的, 有些界面的 listview 第一行是可以 左右滑动的 viewpager,当滑动下面listView的时候 会一起滑动上去 工程目录: 效果图:                   ...

  9. Android实现图片轮显效果——自定义ViewPager控件

    一.问题概述 使用ViewPager控件实现可横向翻页.水平切换图片等效果,但ViewPager需要手动滑动才能切换页面,图片轮显效果的效果本质上就是在ViewPager控件的基础上让它能自动的进行切 ...

随机推荐

  1. IIS 503 错误

    今天早上乘公交的时候,网站运维群里直接炸了,网站打不开,503错误.然后就各种@我,吓得我手机都要扔了,然后马不停蹄的赶往公司去查看错误. 我首先在IIS上浏览网页,想试图在服务器上显现出详细错误,这 ...

  2. OFDM同步算法之Minn算法

    minn算法代码 算法原理 训练序列结构 T=[B B -B -B],其中B表示由长度为N/4的复伪随机序列PN,ifft变换得到的符号序列 (原文解释):B represent samples of ...

  3. 客户端通过base64上传bitmap服务器

    首先致谢:http://www.jb51.net/article/129743.htm 咱们不是代码的生产者,只是代码的搬运工. 场景描述:Android客户端需要上传头像等图片到服务器,经双方协商决 ...

  4. JS——scroll动画

    固定导航栏 1.计算导航栏到顶部的距离值 2.当scrollTop值大于这个距离值就添加定位,当小于距离值后解除定位 注意事项:当导航栏添加定位之后,导航栏就脱离了文档流,也就是不占位了,下面的盒子就 ...

  5. ASP.net参数传递总结

    同一页面.aspx与.aspx.cs之间参数传递 1. .aspx.cs接收.aspx的参数:由于.aspx和.aspx.cs为继承关系,所以.aspx.cs可以直接对.aspx中的ID进行值提取,具 ...

  6. Scrapy爬虫框架 基础

    1< scrapy的安装 命令行安装 pip install scrapy <常见错误是缺少 wim32api 安装win32api pip install pywin32 <还有就 ...

  7. Day 27 网络编程

    目录 网络架构及演变过程 网络架构 互联网和互联网的组成 互联网的组成(教材版) 互联网的组成(科普版) 互联网的硬件组成 互联网的软件组成 OSI七层协议 物理层 数据链路层 网络架构及演变过程 网 ...

  8. B.2 列表

    从很多方面来说,列表是最简单也最自然的集合类型.框架中包含很多实现,具有各种功能 和性能特征.一些常用的实现在哪里都可以使用,而一些较有难度的实现则有其专门的使用场景. B.2.1  List< ...

  9. Neo4j图数据库从入门到精通

    目录 第一章:介绍 Neo4j是什么 Neo4j的特点 Neo4j的优点 第二章:安装 1.环境 2.下载 3.开启远程访问 4.启动 第三章:CQL 1.CQL简介 2.Neo4j CQL命令/条款 ...

  10. 【解题报告】洛谷 P1231 教辅的组成

    [解题报告]洛谷 P1231 教辅的组成 题目链接 CSDN链接 这道题就只是一道普通的最大流问题,但是关键所在就是如何构图.要不是我看了题解,真的想不到这个构图方法呢 题目大意我就不写了,自己看好了 ...