由主页界面引出的几个知识点(五)


一:
自定义View之onMeasure()
可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象。再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定义View。
本节我们探索自定义View中onMeasure()起到了什么样的作用,题外要插的一句是,Activity框架,View框架中大量的on函数基本上都应用到了Template模式,掌握这一模式对于理解这些框架大有裨益。
我们知道,不管是自定义View还是系统提供的TextView这些,它们都必须放置在LinearLayout等一些ViewGroup中,因此理论上我们可以很好的理解onMeasure(),onLayout(),onDraw()这三个函数:1.View本身大小多少,这由onMeasure()决定;2.View在ViewGroup中的位置如何,这由onLayout()决定;3.绘制View,onDraw()定义了如何绘制这个View。

首先我们要理解的是widthMeasureSpec, heightMeasureSpec这两个参数是从哪里来的?onMeasure()函数由包含这个View的具体的ViewGroup调用,因此值也是从这个ViewGroup中传入的。这里我直接给出答案:子类View的这两个参数,由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定。权值weight也是尤其需要考虑的因素,有它的存在情况可能会稍微复杂点。
二: ViewConfiguration.getScaledTouchSlop ()
三:
实现这种不等长圆角PageIndicator

CustomLinePageIndicator
mPaintSelected.setStrokeCap(Paint.Cap.ROUND);//处理圆角
mPaintUnselected.setStrokeCap(Paint.Cap.ROUND);

//处理不等长
for ( int i = 0 ; i < count ; ++i) {

float dx1 = i > this . mCurrentPage ?horizontalOffset + ( float )i * lineWidthAndGap+ 20 :horizontalOffset + ( float )i * lineWidthAndGap ;
float dx2 = dx1 + (i == this . mCurrentPage ? this . mLineWidth + 20 : this . mLineWidth ) ;
canvas.drawLine(dx1 , verticalOffset , dx2 , verticalOffset , i == this . mCurrentPage ? this . mPaintSelected : this . mPaintUnselected ) ;
}
完整代码:


import android.content.Context ;
import android.content.res.Resources ;
import android.content.res.TypedArray ;
import android.graphics.Canvas ;
import android.graphics.Paint ;
import android.graphics.drawable.Drawable ;
import android.os.Parcel ;
import android.os.Parcelable ;
import android.support.v4.view.MotionEventCompat ;
import android.support.v4.view.PagerAdapter ;
import android.support.v4.view.ViewConfigurationCompat ;
import android.support.v4.view.ViewPager ;
import android.util.AttributeSet ;
import android.util.FloatMath ;
import android.view.MotionEvent ;
import android.view.View ;
import android.view.ViewConfiguration ;

import com.viewpagerindicator.LinePageIndicator ;
import com.viewpagerindicator.PageIndicator ;


/**
* Created by chao on 2017/11/22.

*/

public class CustomLinePageIndicator extends View implements PageIndicator {
private static final int INVALID_POINTER = - 1 ;
private final Paint mPaintUnselected ;
private final Paint mPaintSelected ;
private ViewPager mViewPager ;
private ViewPager.OnPageChangeListener mListener ;
private int mCurrentPage ;
private boolean mCentered ;
private float mLineWidth ;
private float mGapWidth ;
private int mTouchSlop ;
private float mLastMotionX ;
private int mActivePointerId ;
private boolean mIsDragging ;


public CustomLinePageIndicator (Context context) {
this (context , (AttributeSet) null ) ;
}

public CustomLinePageIndicator (Context context , AttributeSet attrs) {
this (context , attrs , com.viewpagerindicator.R.attr. vpiLinePageIndicatorStyle ) ;
}

public CustomLinePageIndicator (Context context , AttributeSet attrs , int defStyle) {
super (context , attrs , defStyle) ;
this . mPaintUnselected = new Paint( 1 ) ;
mPaintUnselected .setStrokeCap(Paint.Cap. ROUND ) ;
this . mPaintSelected = new Paint( 1 ) ;
mPaintSelected .setStrokeCap(Paint.Cap. ROUND ) ;
this . mLastMotionX = - 1.0F ;
this . mActivePointerId = - 1 ;
if (! this .isInEditMode()) {
Resources res = this .getResources() ;
int defaultSelectedColor = res.getColor(com.viewpagerindicator.R.color. default_line_indicator_selected_color ) ;
int defaultUnselectedColor = res.getColor(com.viewpagerindicator.R.color. default_line_indicator_unselected_color ) ;
float defaultLineWidth = res.getDimension(com.viewpagerindicator.R.dimen. default_line_indicator_line_width )- 5 ;
float defaultGapWidth = res.getDimension(com.viewpagerindicator.R.dimen. default_line_indicator_gap_width )+ 20 ;
float defaultStrokeWidth = res.getDimension(com.viewpagerindicator.R.dimen. default_line_indicator_stroke_width ) ;
boolean defaultCentered = res.getBoolean(com.viewpagerindicator.R.bool. default_line_indicator_centered ) ;
TypedArray a = context.obtainStyledAttributes(attrs , com.viewpagerindicator.R.styleable. LinePageIndicator , defStyle , 0 ) ;
this . mCentered = a.getBoolean( 1 , defaultCentered) ;
this . mLineWidth = a.getDimension( 5 , defaultLineWidth) ;
this . mGapWidth = a.getDimension( 6 , defaultGapWidth) ;
this .setStrokeWidth(a.getDimension( 3 , defaultStrokeWidth+ 5 )) ;
this . mPaintUnselected .setColor(a.getColor( 4 , defaultUnselectedColor)) ;
this . mPaintSelected .setColor(a.getColor( 2 , defaultSelectedColor)) ;
Drawable background = a.getDrawable( 0 ) ;
if (background != null ) {
this .setBackgroundDrawable(background) ;
}

a.recycle() ;
ViewConfiguration configuration = ViewConfiguration. get (context) ;
this . mTouchSlop = ViewConfigurationCompat. getScaledPagingTouchSlop (configuration) ;
}
}

public void setCentered ( boolean centered) {
this . mCentered = centered ;
this .invalidate() ;
}

public boolean isCentered () {
return this . mCentered ;
}

public void setUnselectedColor ( int unselectedColor) {
this . mPaintUnselected .setColor(unselectedColor) ;
this .invalidate() ;
}

public int getUnselectedColor () {
return this . mPaintUnselected .getColor() ;
}

public void setSelectedColor ( int selectedColor) {
this . mPaintSelected .setColor(selectedColor) ;
this .invalidate() ;
}

public int getSelectedColor () {
return this . mPaintSelected .getColor() ;
}

public void setLineWidth ( float lineWidth) {
this . mLineWidth = lineWidth ;
this .invalidate() ;
}

public float getLineWidth () {
return this . mLineWidth ;
}

public void setStrokeWidth ( float lineHeight) {
this . mPaintSelected .setStrokeWidth(lineHeight) ;
this . mPaintUnselected .setStrokeWidth(lineHeight) ;
this .invalidate() ;
}

public float getStrokeWidth () {
return this . mPaintSelected .getStrokeWidth() ;
}

public void setGapWidth ( float gapWidth) {
this . mGapWidth = gapWidth ;
this .invalidate() ;
}

public float getGapWidth () {
return this . mGapWidth ;
}

protected void onDraw (Canvas canvas) {
super .onDraw(canvas) ;
if ( this . mViewPager != null ) {
int count = this . mViewPager .getAdapter().getCount() ;
if (count != 0 ) {
if ( this . mCurrentPage >= count) {
this .setCurrentItem(count - 1 ) ;
} else {
float lineWidthAndGap = this . mLineWidth + this . mGapWidth ;
float indicatorWidth = ( float )count * lineWidthAndGap - this . mGapWidth ;
float paddingTop = ( float ) this .getPaddingTop() ;
float paddingLeft = ( float ) this .getPaddingLeft() ;
float paddingRight = ( float ) this .getPaddingRight() ;
float verticalOffset = paddingTop + (( float ) this .getHeight() - paddingTop - ( float ) this .getPaddingBottom()) / 2.0F ;
float horizontalOffset = paddingLeft ;
if ( this . mCentered ) {
horizontalOffset = paddingLeft + ((( float ) this .getWidth() - paddingLeft - paddingRight) / 2.0F - indicatorWidth / 2.0F ) ;
}
for ( int i = 0 ; i < count ; ++i) {
float dx1 = i > this . mCurrentPage ?horizontalOffset + ( float )i * lineWidthAndGap+ 15 :horizontalOffset + ( float )i * lineWidthAndGap ;
float dx2 = dx1 + (i == this . mCurrentPage ? this . mLineWidth + 15 : this . mLineWidth ) ;
canvas.drawLine(dx1 , verticalOffset , dx2 , verticalOffset , i == this . mCurrentPage ? this . mPaintSelected : this . mPaintUnselected ) ;
}
}
}
}
}


public boolean onTouchEvent (MotionEvent ev) {
if ( super .onTouchEvent(ev)) {
return true;
} else if ( this . mViewPager != null && this . mViewPager .getAdapter().getCount() != 0 ) {
int action = ev.getAction() & 255 ;
int count ;
int width ;
float deltaX ;
switch (action) {
case 0 :
this . mActivePointerId = MotionEventCompat. getPointerId (ev , 0 ) ;
this . mLastMotionX = ev.getX() ;
break;
case 1 :
case 3 :
if (! this . mIsDragging ) {
count = this . mViewPager .getAdapter().getCount() ;
width = this .getWidth() ;
deltaX = ( float )width / 2.0F ;
float sixthWidth = ( float )width / 6.0F ;
if ( this . mCurrentPage > 0 && ev.getX() < deltaX - sixthWidth) {
if (action != 3 ) {
this . mViewPager .setCurrentItem( this . mCurrentPage - 1 ) ;
}

return true;
}

if ( this . mCurrentPage < count - 1 && ev.getX() > deltaX + sixthWidth) {
if (action != 3 ) {
this . mViewPager .setCurrentItem( this . mCurrentPage + 1 ) ;
}

return true;
}
}

this . mIsDragging = false;
this . mActivePointerId = - 1 ;
if ( this . mViewPager .isFakeDragging()) {
this . mViewPager .endFakeDrag() ;
}
break;
case 2 :
count = MotionEventCompat. findPointerIndex (ev , this . mActivePointerId ) ;
float x = MotionEventCompat. getX (ev , count) ;
deltaX = x - this . mLastMotionX ;
if (! this . mIsDragging && Math. abs (deltaX) > ( float ) this . mTouchSlop ) {
this . mIsDragging = true;
}

if ( this . mIsDragging ) {
this . mLastMotionX = x ;
if ( this . mViewPager .isFakeDragging() || this . mViewPager .beginFakeDrag()) {
this . mViewPager .fakeDragBy(deltaX) ;
}
}
case 4 :
default :
break;
case 5 :
count = MotionEventCompat. getActionIndex (ev) ;
this . mLastMotionX = MotionEventCompat. getX (ev , count) ;
this . mActivePointerId = MotionEventCompat. getPointerId (ev , count) ;
break;
case 6 :
count = MotionEventCompat. getActionIndex (ev) ;
width = MotionEventCompat. getPointerId (ev , count) ;
if (width == this . mActivePointerId ) {
int newPointerIndex = count == 0 ? 1 : 0 ;
this . mActivePointerId = MotionEventCompat. getPointerId (ev , newPointerIndex) ;
}

this . mLastMotionX = MotionEventCompat. getX (ev , MotionEventCompat. findPointerIndex (ev , this . mActivePointerId )) ;
}

return true;
} else {
return false;
}
}

public void setViewPager (ViewPager viewPager) {
if ( this . mViewPager != viewPager) {
if ( this . mViewPager != null ) {
this . mViewPager .setOnPageChangeListener((ViewPager.OnPageChangeListener) null ) ;
}

if (viewPager.getAdapter() == null ) {
throw new IllegalStateException( "ViewPager does not have adapter instance." ) ;
} else {
this . mViewPager = viewPager ;
this . mViewPager .setOnPageChangeListener( this ) ;
this .invalidate() ;
}
}
}

public void setViewPager (ViewPager view , int initialPosition) {
this .setViewPager(view) ;
this .setCurrentItem(initialPosition) ;
}

public void setCurrentItem ( int item) {
if ( this . mViewPager == null ) {
throw new IllegalStateException( "ViewPager has not been bound." ) ;
} else {
this . mViewPager .setCurrentItem(item) ;
this . mCurrentPage = item ;
this .invalidate() ;
}
}

public void notifyDataSetChanged () {
this .invalidate() ;
}

public void onPageScrollStateChanged ( int state) {
if ( this . mListener != null ) {
this . mListener .onPageScrollStateChanged(state) ;
}

}

public void onPageScrolled ( int position , float positionOffset , int positionOffsetPixels) {
if ( this . mListener != null ) {
this . mListener .onPageScrolled(position , positionOffset , positionOffsetPixels) ;
}

}

public void onPageSelected ( int position) {
this . mCurrentPage = position ;
this .invalidate() ;
if ( this . mListener != null ) {
this . mListener .onPageSelected(position) ;
}

}

public void setOnPageChangeListener (ViewPager.OnPageChangeListener listener) {
this . mListener = listener ;
}

protected void onMeasure ( int widthMeasureSpec , int heightMeasureSpec) {
this .setMeasuredDimension( this .measureWidth(widthMeasureSpec) , this .measureHeight(heightMeasureSpec)) ;
}

private int measureWidth ( int measureSpec) {
int specMode = MeasureSpec. getMode (measureSpec) ;
int specSize = MeasureSpec. getSize (measureSpec) ;
float result ;
if (specMode != 1073741824 && this . mViewPager != null ) {
int count = this . mViewPager .getAdapter().getCount() ;
result = ( float )( this .getPaddingLeft() + this .getPaddingRight()) + ( float )(count * this . mLineWidth )+ 20 + + ( float )(count - 1 ) * this . mGapWidth ;
if (specMode == - 2147483648 ) {
result = Math. min (result , ( float )specSize) ;
}
} else {
result = ( float )specSize ;
}

return ( int ) Math. ceil (result) ;
}

private int measureHeight ( int measureSpec) {
int specMode = MeasureSpec. getMode (measureSpec) ;
int specSize = MeasureSpec. getSize (measureSpec) ;
float result ;
if (specMode == 1073741824 ) {
result = ( float )specSize ;
} else {
result = this . mPaintSelected .getStrokeWidth() + ( float ) this .getPaddingTop() + ( float ) this .getPaddingBottom() ;
if (specMode == - 2147483648 ) {
result = Math. min (result , ( float )specSize) ;
}
}

return ( int ) Math. ceil (result) ;
}

public void onRestoreInstanceState (Parcelable state) {
CustomLinePageIndicator.SavedState savedState = (CustomLinePageIndicator.SavedState)state ;
super .onRestoreInstanceState(savedState.getSuperState()) ;
this . mCurrentPage = savedState. currentPage ;
this .requestLayout() ;
}

public Parcelable onSaveInstanceState () {
Parcelable superState = super .onSaveInstanceState() ;
CustomLinePageIndicator.SavedState savedState = new CustomLinePageIndicator.SavedState(superState) ;
savedState. currentPage = this . mCurrentPage ;
return savedState ;
}

static class SavedState extends View.BaseSavedState {
int currentPage ;
public static final Creator<CustomLinePageIndicator.SavedState> CREATOR = new Creator<CustomLinePageIndicator.SavedState>() {
public CustomLinePageIndicator.SavedState createFromParcel (Parcel in) {
return new CustomLinePageIndicator.SavedState(in) ;
}

public CustomLinePageIndicator.SavedState[] newArray ( int size) {
return new CustomLinePageIndicator.SavedState[size] ;
}
} ;

public SavedState (Parcelable superState) {
super (superState) ;
}

private SavedState (Parcel in) {
super (in) ;
this . currentPage = in.readInt() ;
}

public void writeToParcel (Parcel dest , int flags) {
super .writeToParcel(dest , flags) ;
dest.writeInt( this . currentPage ) ;
}
}
}


一:
自定义View之onMeasure()
可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象。再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定义View。
本节我们探索自定义View中onMeasure()起到了什么样的作用,题外要插的一句是,Activity框架,View框架中大量的on函数基本上都应用到了Template模式,掌握这一模式对于理解这些框架大有裨益。

我们知道,不管是自定义View还是系统提供的TextView这些,它们都必须放置在LinearLayout等一些ViewGroup中,因此理论上我们可以很好的理解onMeasure(),onLayout(),onDraw()这三个函数:1.View本身大小多少,这由onMeasure()决定;2.View在ViewGroup中的位置如何,这由onLayout()决定;3.绘制View,onDraw()定义了如何绘制这个View。

首先我们要理解的是widthMeasureSpec, heightMeasureSpec这两个参数是从哪里来的?onMeasure()函数由包含这个View的具体的ViewGroup调用,因此值也是从这个ViewGroup中传入的。这里我直接给出答案:子类View的这两个参数,由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同决定。权值weight也是尤其需要考虑的因素,有它的存在情况可能会稍微复杂点。
二: ViewConfiguration.getScaledTouchSlop ()
三:
实现这种不等长圆角PageIndicator

CustomLinePageIndicator
mPaintSelected.setStrokeCap(Paint.Cap.ROUND);//处理圆角
mPaintUnselected.setStrokeCap(Paint.Cap.ROUND);

//处理不等长
for ( int i = 0 ; i < count ; ++i) {

float dx1 = i > this . mCurrentPage ?horizontalOffset + ( float )i * lineWidthAndGap+ 20 :horizontalOffset + ( float )i * lineWidthAndGap ;
float dx2 = dx1 + (i == this . mCurrentPage ? this . mLineWidth + 20 : this . mLineWidth ) ;
canvas.drawLine(dx1 , verticalOffset , dx2 , verticalOffset , i == this . mCurrentPage ? this . mPaintSelected : this . mPaintUnselected ) ;
}
完整代码:


import android.content.Context ;
import android.content.res.Resources ;
import android.content.res.TypedArray ;
import android.graphics.Canvas ;
import android.graphics.Paint ;
import android.graphics.drawable.Drawable ;
import android.os.Parcel ;
import android.os.Parcelable ;
import android.support.v4.view.MotionEventCompat ;
import android.support.v4.view.PagerAdapter ;
import android.support.v4.view.ViewConfigurationCompat ;
import android.support.v4.view.ViewPager ;
import android.util.AttributeSet ;
import android.util.FloatMath ;
import android.view.MotionEvent ;
import android.view.View ;
import android.view.ViewConfiguration ;

import com.viewpagerindicator.LinePageIndicator ;
import com.viewpagerindicator.PageIndicator ;


/**
* Created by chao on 2017/11/22.

*/

public class CustomLinePageIndicator extends View implements PageIndicator {
private static final int INVALID_POINTER = - 1 ;
private final Paint mPaintUnselected ;
private final Paint mPaintSelected ;
private ViewPager mViewPager ;
private ViewPager.OnPageChangeListener mListener ;
private int mCurrentPage ;
private boolean mCentered ;
private float mLineWidth ;
private float mGapWidth ;
private int mTouchSlop ;
private float mLastMotionX ;
private int mActivePointerId ;
private boolean mIsDragging ;


public CustomLinePageIndicator (Context context) {
this (context , (AttributeSet) null ) ;
}

public CustomLinePageIndicator (Context context , AttributeSet attrs) {
this (context , attrs , com.viewpagerindicator.R.attr. vpiLinePageIndicatorStyle ) ;
}

public CustomLinePageIndicator (Context context , AttributeSet attrs , int defStyle) {
super (context , attrs , defStyle) ;
this . mPaintUnselected = new Paint( 1 ) ;
mPaintUnselected .setStrokeCap(Paint.Cap. ROUND ) ;
this . mPaintSelected = new Paint( 1 ) ;
mPaintSelected .setStrokeCap(Paint.Cap. ROUND ) ;
this . mLastMotionX = - 1.0F ;
this . mActivePointerId = - 1 ;
if (! this .isInEditMode()) {
Resources res = this .getResources() ;
int defaultSelectedColor = res.getColor(com.viewpagerindicator.R.color. default_line_indicator_selected_color ) ;
int defaultUnselectedColor = res.getColor(com.viewpagerindicator.R.color. default_line_indicator_unselected_color ) ;
float defaultLineWidth = res.getDimension(com.viewpagerindicator.R.dimen. default_line_indicator_line_width )- 5 ;
float defaultGapWidth = res.getDimension(com.viewpagerindicator.R.dimen. default_line_indicator_gap_width )+ 20 ;
float defaultStrokeWidth = res.getDimension(com.viewpagerindicator.R.dimen. default_line_indicator_stroke_width ) ;
boolean defaultCentered = res.getBoolean(com.viewpagerindicator.R.bool. default_line_indicator_centered ) ;
TypedArray a = context.obtainStyledAttributes(attrs , com.viewpagerindicator.R.styleable. LinePageIndicator , defStyle , 0 ) ;
this . mCentered = a.getBoolean( 1 , defaultCentered) ;
this . mLineWidth = a.getDimension( 5 , defaultLineWidth) ;
this . mGapWidth = a.getDimension( 6 , defaultGapWidth) ;
this .setStrokeWidth(a.getDimension( 3 , defaultStrokeWidth+ 5 )) ;
this . mPaintUnselected .setColor(a.getColor( 4 , defaultUnselectedColor)) ;
this . mPaintSelected .setColor(a.getColor( 2 , defaultSelectedColor)) ;
Drawable background = a.getDrawable( 0 ) ;
if (background != null ) {
this .setBackgroundDrawable(background) ;
}

a.recycle() ;
ViewConfiguration configuration = ViewConfiguration. get (context) ;
this . mTouchSlop = ViewConfigurationCompat. getScaledPagingTouchSlop (configuration) ;
}
}

public void setCentered ( boolean centered) {
this . mCentered = centered ;
this .invalidate() ;
}

public boolean isCentered () {
return this . mCentered ;
}

public void setUnselectedColor ( int unselectedColor) {
this . mPaintUnselected .setColor(unselectedColor) ;
this .invalidate() ;
}

public int getUnselectedColor () {
return this . mPaintUnselected .getColor() ;
}

public void setSelectedColor ( int selectedColor) {
this . mPaintSelected .setColor(selectedColor) ;
this .invalidate() ;
}

public int getSelectedColor () {
return this . mPaintSelected .getColor() ;
}

public void setLineWidth ( float lineWidth) {
this . mLineWidth = lineWidth ;
this .invalidate() ;
}

public float getLineWidth () {
return this . mLineWidth ;
}

public void setStrokeWidth ( float lineHeight) {
this . mPaintSelected .setStrokeWidth(lineHeight) ;
this . mPaintUnselected .setStrokeWidth(lineHeight) ;
this .invalidate() ;
}

public float getStrokeWidth () {
return this . mPaintSelected .getStrokeWidth() ;
}

public void setGapWidth ( float gapWidth) {
this . mGapWidth = gapWidth ;
this .invalidate() ;
}

public float getGapWidth () {
return this . mGapWidth ;
}

protected void onDraw (Canvas canvas) {
super .onDraw(canvas) ;
if ( this . mViewPager != null ) {
int count = this . mViewPager .getAdapter().getCount() ;
if (count != 0 ) {
if ( this . mCurrentPage >= count) {
this .setCurrentItem(count - 1 ) ;
} else {
float lineWidthAndGap = this . mLineWidth + this . mGapWidth ;
float indicatorWidth = ( float )count * lineWidthAndGap - this . mGapWidth ;
float paddingTop = ( float ) this .getPaddingTop() ;
float paddingLeft = ( float ) this .getPaddingLeft() ;
float paddingRight = ( float ) this .getPaddingRight() ;
float verticalOffset = paddingTop + (( float ) this .getHeight() - paddingTop - ( float ) this .getPaddingBottom()) / 2.0F ;
float horizontalOffset = paddingLeft ;
if ( this . mCentered ) {
horizontalOffset = paddingLeft + ((( float ) this .getWidth() - paddingLeft - paddingRight) / 2.0F - indicatorWidth / 2.0F ) ;
}
for ( int i = 0 ; i < count ; ++i) {
float dx1 = i > this . mCurrentPage ?horizontalOffset + ( float )i * lineWidthAndGap+ 15 :horizontalOffset + ( float )i * lineWidthAndGap ;
float dx2 = dx1 + (i == this . mCurrentPage ? this . mLineWidth + 15 : this . mLineWidth ) ;
canvas.drawLine(dx1 , verticalOffset , dx2 , verticalOffset , i == this . mCurrentPage ? this . mPaintSelected : this . mPaintUnselected ) ;
}
}
}
}
}


public boolean onTouchEvent (MotionEvent ev) {
if ( super .onTouchEvent(ev)) {
return true;
} else if ( this . mViewPager != null && this . mViewPager .getAdapter().getCount() != 0 ) {
int action = ev.getAction() & 255 ;
int count ;
int width ;
float deltaX ;
switch (action) {
case 0 :
this . mActivePointerId = MotionEventCompat. getPointerId (ev , 0 ) ;
this . mLastMotionX = ev.getX() ;
break;
case 1 :
case 3 :
if (! this . mIsDragging ) {
count = this . mViewPager .getAdapter().getCount() ;
width = this .getWidth() ;
deltaX = ( float )width / 2.0F ;
float sixthWidth = ( float )width / 6.0F ;
if ( this . mCurrentPage > 0 && ev.getX() < deltaX - sixthWidth) {
if (action != 3 ) {
this . mViewPager .setCurrentItem( this . mCurrentPage - 1 ) ;
}

return true;
}

if ( this . mCurrentPage < count - 1 && ev.getX() > deltaX + sixthWidth) {
if (action != 3 ) {
this . mViewPager .setCurrentItem( this . mCurrentPage + 1 ) ;
}

return true;
}
}

this . mIsDragging = false;
this . mActivePointerId = - 1 ;
if ( this . mViewPager .isFakeDragging()) {
this . mViewPager .endFakeDrag() ;
}
break;
case 2 :
count = MotionEventCompat. findPointerIndex (ev , this . mActivePointerId ) ;
float x = MotionEventCompat. getX (ev , count) ;
deltaX = x - this . mLastMotionX ;
if (! this . mIsDragging && Math. abs (deltaX) > ( float ) this . mTouchSlop ) {
this . mIsDragging = true;
}

if ( this . mIsDragging ) {
this . mLastMotionX = x ;
if ( this . mViewPager .isFakeDragging() || this . mViewPager .beginFakeDrag()) {
this . mViewPager .fakeDragBy(deltaX) ;
}
}
case 4 :
default :
break;
case 5 :
count = MotionEventCompat. getActionIndex (ev) ;
this . mLastMotionX = MotionEventCompat. getX (ev , count) ;
this . mActivePointerId = MotionEventCompat. getPointerId (ev , count) ;
break;
case 6 :
count = MotionEventCompat. getActionIndex (ev) ;
width = MotionEventCompat. getPointerId (ev , count) ;
if (width == this . mActivePointerId ) {
int newPointerIndex = count == 0 ? 1 : 0 ;
this . mActivePointerId = MotionEventCompat. getPointerId (ev , newPointerIndex) ;
}

this . mLastMotionX = MotionEventCompat. getX (ev , MotionEventCompat. findPointerIndex (ev , this . mActivePointerId )) ;
}

return true;
} else {
return false;
}
}

public void setViewPager (ViewPager viewPager) {
if ( this . mViewPager != viewPager) {
if ( this . mViewPager != null ) {
this . mViewPager .setOnPageChangeListener((ViewPager.OnPageChangeListener) null ) ;
}

if (viewPager.getAdapter() == null ) {
throw new IllegalStateException( "ViewPager does not have adapter instance." ) ;
} else {
this . mViewPager = viewPager ;
this . mViewPager .setOnPageChangeListener( this ) ;
this .invalidate() ;
}
}
}

public void setViewPager (ViewPager view , int initialPosition) {
this .setViewPager(view) ;
this .setCurrentItem(initialPosition) ;
}

public void setCurrentItem ( int item) {
if ( this . mViewPager == null ) {
throw new IllegalStateException( "ViewPager has not been bound." ) ;
} else {
this . mViewPager .setCurrentItem(item) ;
this . mCurrentPage = item ;
this .invalidate() ;
}
}

public void notifyDataSetChanged () {
this .invalidate() ;
}

public void onPageScrollStateChanged ( int state) {
if ( this . mListener != null ) {
this . mListener .onPageScrollStateChanged(state) ;
}

}

public void onPageScrolled ( int position , float positionOffset , int positionOffsetPixels) {
if ( this . mListener != null ) {
this . mListener .onPageScrolled(position , positionOffset , positionOffsetPixels) ;
}

}

public void onPageSelected ( int position) {
this . mCurrentPage = position ;
this .invalidate() ;
if ( this . mListener != null ) {
this . mListener .onPageSelected(position) ;
}

}

public void setOnPageChangeListener (ViewPager.OnPageChangeListener listener) {
this . mListener = listener ;
}

protected void onMeasure ( int widthMeasureSpec , int heightMeasureSpec) {
this .setMeasuredDimension( this .measureWidth(widthMeasureSpec) , this .measureHeight(heightMeasureSpec)) ;
}

private int measureWidth ( int measureSpec) {
int specMode = MeasureSpec. getMode (measureSpec) ;
int specSize = MeasureSpec. getSize (measureSpec) ;
float result ;
if (specMode != 1073741824 && this . mViewPager != null ) {
int count = this . mViewPager .getAdapter().getCount() ;
result = ( float )( this .getPaddingLeft() + this .getPaddingRight()) + ( float )(count * this . mLineWidth )+ 20 + + ( float )(count - 1 ) * this . mGapWidth ;
if (specMode == - 2147483648 ) {
result = Math. min (result , ( float )specSize) ;
}
} else {
result = ( float )specSize ;
}

return ( int ) Math. ceil (result) ;
}

private int measureHeight ( int measureSpec) {
int specMode = MeasureSpec. getMode (measureSpec) ;
int specSize = MeasureSpec. getSize (measureSpec) ;
float result ;
if (specMode == 1073741824 ) {
result = ( float )specSize ;
} else {
result = this . mPaintSelected .getStrokeWidth() + ( float ) this .getPaddingTop() + ( float ) this .getPaddingBottom() ;
if (specMode == - 2147483648 ) {
result = Math. min (result , ( float )specSize) ;
}
}

return ( int ) Math. ceil (result) ;
}

public void onRestoreInstanceState (Parcelable state) {
CustomLinePageIndicator.SavedState savedState = (CustomLinePageIndicator.SavedState)state ;
super .onRestoreInstanceState(savedState.getSuperState()) ;
this . mCurrentPage = savedState. currentPage ;
this .requestLayout() ;
}

public Parcelable onSaveInstanceState () {
Parcelable superState = super .onSaveInstanceState() ;
CustomLinePageIndicator.SavedState savedState = new CustomLinePageIndicator.SavedState(superState) ;
savedState. currentPage = this . mCurrentPage ;
return savedState ;
}

static class SavedState extends View.BaseSavedState {
int currentPage ;
public static final Creator<CustomLinePageIndicator.SavedState> CREATOR = new Creator<CustomLinePageIndicator.SavedState>() {
public CustomLinePageIndicator.SavedState createFromParcel (Parcel in) {
return new CustomLinePageIndicator.SavedState(in) ;
}

public CustomLinePageIndicator.SavedState[] newArray ( int size) {
return new CustomLinePageIndicator.SavedState[size] ;
}
} ;

public SavedState (Parcelable superState) {
super (superState) ;
}

private SavedState (Parcel in) {
super (in) ;
this . currentPage = in.readInt() ;
}

public void writeToParcel (Parcel dest , int flags) {
super .writeToParcel(dest , flags) ;
dest.writeInt( this . currentPage ) ;
}
}
}

猜你喜欢

转载自blog.csdn.net/qq_27073205/article/details/78658673