努力尽今夕,少年犹可夸。这篇文章主要讲述Android之自己定义(上方标题随ViewPager手势慢慢滑动)相关的知识,希望能为你提供帮助。
近期非常蛋疼,项目要模仿网易新闻的样式去做。上次把仿网易新闻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:这个做的还不是非常完好。另一些东西没有做适配。
假设有人用,在使用过程中出现故障,你能够自己做一下简单的适配。
源代码下载地址: 【Android之自己定义(上方标题随ViewPager手势慢慢滑动)】http://pan.baidu.com/s/1sj0lIxR
我的github地址:https://github.com/flyme2012 我的博客园 博客地址:http://www.cnblogs.com/flyme2012/
推荐阅读
- Android中常见的设计模式
- Android Studio底边栏选项不见了,怎样调出来
- Android开发时经经常使用的LogUtil
- Tomcat启动时卡在“INFO: Deploying web application directory ......”的解决方法
- Android HAL模块实现
- android定时操作
- 《Android源代码设计模式解析与实战》读书笔记(二十三)
- 《CS(APP》 chapter 9Vitrual Memory 笔记)
- android 判断Service是否在运行