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/

时间: 2024-08-06 18:45:12

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

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

近期非常蛋疼,项目要模仿网易新闻的样式去做.上次把仿网易新闻client的下拉刷新写出来了.这次是ViewPager的滑动,同一时候ViewPager的上面标题下划线尾随者移动.本来通过ViewPager的OnPagerChangeListener的监听事件就能够完毕,可是做出来之后,由于须要一直的刷新,所以非常卡.一气之下.呵呵.自己全然的画了.整个点击事件,滑动事件都自己处理了. 效果图例如以下: 下标的长宽是随之改变的. 使用方式: 我的布局文件: <LinearLayout xmlns:

Android ViewPager内容部分随手势上下滑动隐藏与显示Indicator效果的实现

效果 ViewPager中的内容,比如ListView手势上下滑动,当内容向下滑动时,即手势上划,隐藏indictor,当内容向上滑动时,即手势下滑,显示indicator,效果如图所示 编码 借用两个库来快速完成 1. ViewPagerIndicator 2. ObservableScrollView 将两个库引入项目中去,快速的搭建一个ViewPager框架后,在ViewPager每页对应的Fragment的布局中增加一个ListView,这个ListView使用ObservableScr

Android peferenceActivity 自定义标题简单方法

Android peferenceActivity 自定义标题简单方法 peferenceActivity 完全使用定义好的布局. 因此不能简单象其它好窗口进行自定,现在我们需要加 一个自定义标题,比如象其它窗口一样加一个统一topbar. 假设这个topbar的布局是 title.xml 一.标准自定义标题栏方法 Android 提供自定义标题栏方法 我们简单实现. @Override protected void onCreate(Bundle savedInstanceState) { f

android 在开发WebView时,去掉网页的标题并设置成自定义的标题

IOS中关于去掉标题只需类似下面的两行代码 [js appendString:@"var title = document.getElementsByClassName('navbar-top')[0];"]; [js appendString:@"title.parentNode.removeChild(title);"]; 而android上面拿掉网页的标题还真是难事,自己花了好几天的时间终于大功告成,现目前这绝对是拿掉标题换成自定义的标题的第一人.网上的都是更

Android控件的新宠儿——ViewPager

1 认识一下ViewPager? ViewPager最早出自4.0版本,那么低版本如何能使用ViewPager呢?为了兼容低版本安卓设备,谷歌官方给我们提供了一个的软件包android.support.v4.view.这个V4包囊了只有在安卓3.0以上可以使用的api,而viewpager就是其中之一.利用它,我们可以做很多事情,从最简单的引导页导航,到轮转广告,到页面菜单等等,无不出现ViewPager的身影.应用广泛,简单好用,更好的交互性,这也是ViewPager一出现便大受程序员欢迎的原

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

一.问题描述 在Android典型界面设计一文中,实现典型滑动导航界面,其实使用ActionBar 也可以轻松实现这一效果,甚至也可实现类似Android典型界面设计(3)的双导航效果.可见ActionBar还是比较强大的,关键要深入进去.灵活的运用,下面我们就使用ActionBar实现如图所示的效果: 二.本例特点 1.  兼容低版本 2. 使用ActionBar 分体设计(split) 3. Tab使用自定义View 4. 结合ViewPager实现滑动导航 三.代码讲解: 1.在项目中加入

自定义ActionBar标题与菜单中的文字样式

自定义标题文字样式 标题样式是ActionBar样式的一部分,所以要先定义ActionBar的样式 <style name="AppTheme" parent="AppBaseTheme"> <item name="android:actionBarStyle">@style/CustomActionBar</item> </style> 然后在ActionBar的样式中通过android:titl

【2014年最后的分享啦】Android实现自定义刮刮卡效果View

一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文<Android实现自定义圆形.圆角和椭圆ImageView(使用Xfermode图形渲染方法)>, 今天我们来看看如何实现电商app里常用到的刮刮卡效果的view组件,其实原理和实现圆角图片的差不多,都是使用Xfermode渲染模式来实现的. (老规矩,源码在博文最后给出哈) 基本原理步骤是这样的

自定义View 之利用ViewPager 实现画廊效果(滑动放大缩小)

自定义View 之利用ViewPager 实现画廊效果(滑动放大缩小) 转载请标明出处: http://blog.csdn.net/lisdye2/article/details/52315008 本文出自:[Alex_MaHao的博客] 项目中的源码已经共享到github,有需要者请移步[Alex_MaHao的github] 基本介绍 画廊在很多的App设计中都有,如下图所示: 该例子是我没事的时候写的一个小项目,具体源码地址请访问https://github.com/AlexSmille/Y