曾经,我看到QQ浏览器的界面指示图标随着手指滑动的效果,觉得非常好,自己也想实现,自己做了一个《android viewpager 之 基本使用方法》,基本上实现了界面指示图标的功能,但是对于界面指示图标随着手指滑动的效果,自己只是知道是要在OnPageChangeListener类中的onPageScrolled方法中实现,但是多次尝试都没有成功。直到,我看到这篇博文<<Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI>>,才明白了其中的实现方法。
这篇博文,我主要是做二个事情。
一是把指示图标从三角形改换为点,
第二是,将我以前的界面指示图标随着手指滑动的效果实现。
类ViewPagerIndicator的关键方法:
在博文<<Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI>>中,核心类ViewPagerIndicator的关键方法:
onFinishInflate()--------Called after a view and all of its children has been inflated from XML. (从XML文件导入布局文件后调用)
onSizeChanged(int w, int h, int oldw, int oldh)------Called when the size of this view has changed. (当子view 改变大小时调用,主要用来确定子view的大小)
dispatchDraw(Canvas canvas)-------这个方法主要是ViewGroup容器组件的绘制,并分发给子组件进行绘制。所以,在ViewGroup上绘制东西的时候往往重写的是此方法, 而不是onDraw()方法。
scroll(int position, float offset)-----此方法是OnPageChangeListener类中的onPageScrolled方法中的一个方法,主要是在界面滑动时,实时的更新界面指示图标的位置和实时的滚动控件的位置。
(1)res/values/attr.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="item_count" format="integer"></attr> <declare-styleable name="ViewPagerIndicator"> <attr name="item_count" /> <attr name="indicaytor_type"> <enum name="indicaytor_type_circle" value="1"></enum> <enum name="indicaytor_type_triangle" value="2"></enum> </attr> </declare-styleable> </resources>
(2)在布局文件中添加指示图标的样式的属性定义:
custom:indicaytor_type="indicaytor_type_triangle"
custom:indicaytor_type="indicaytor_type_circle"
<!-- custom:indicaytor_type="indicaytor_type_triangle" custom:indicaytor_type="indicaytor_type_circle" --> <com.example.customviewpagerindicator.ViewPagerIndicator android:id="@+id/id_indicator" android:layout_width="match_parent" android:layout_height="45dp" android:background="@drawable/title_bar_bg_one_row" android:orientation="horizontal" custom:item_count="4" custom:indicaytor_type="indicaytor_type_circle" >
定义二种指示图标的样式:
private int indicaytor_type; private int indicaytor_type_circle = 1; private int indicaytor_type_triangle = 2;
indicaytor_type = a.getInt(R.styleable.ViewPagerIndicator_indicaytor_type,indicaytor_type_circle);
protected void dispatchDraw(Canvas canvas) { if(indicaytor_type == indicaytor_type_circle){ canvas.save(); int radius = 6; canvas.translate(mInitTranslationX + mTranslationX, getHeight() - 10); canvas.drawCircle(radius, 0, radius, mPaint); canvas.restore(); }else{ mPaint.setPathEffect(new CornerPathEffect(3)); canvas.save(); canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1); canvas.drawPath(mPath, mPaint); canvas.restore(); } super.dispatchDraw(canvas); }
这个主要是参考<<Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI>>中的scroll(int position, float offset)方法来实现的:
定义移动的参数:
private int mInitTranslationX; private float mTranslationX; private int tabCount = 3;
private void InitImageView() { // TODO Auto-generated method stub imageView= (ImageView) findViewById(R.id.cursor); bmpW = BitmapFactory.decodeResource(getResources(), R.drawable.cursor).getWidth(); Log.i(TAG, "bmpW:"+bmpW); screenW = getScreenWidth(); offset = (screenW / tabCount - bmpW) / 2; mInitTranslationX = screenW / tabCount / 2 - bmpW/ 2; Matrix matrix = new Matrix(); matrix.postTranslate(mInitTranslationX, 0); imageView.setImageMatrix(matrix); }
实现实现移动的效果:
public void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) { mTranslationX = getScreenWidth() / tabCount * (position + positionOffset); Matrix matrix = new Matrix(); matrix.postTranslate(mInitTranslationX+mTranslationX, 0); imageView.setImageMatrix(matrix); }
import java.util.List; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.CornerPathEffect; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.TextView; /** * http://blog.csdn.net/lmj623565791/article/details/42160391 * @author zhy * */ public class ViewPagerIndicator extends LinearLayout { private Paint mPaint; private Path mPath; private int mTriangleWidth; private int mTriangleHeight; private static final float RADIO_TRIANGEL = 1.0f / 6; private final int DIMENSION_TRIANGEL_WIDTH = (int) (getScreenWidth() / 3 * RADIO_TRIANGEL); private int mInitTranslationX; private float mTranslationX; private static final int COUNT_DEFAULT_TAB = 4; private int mTabVisibleCount = COUNT_DEFAULT_TAB; private List<String> mTabTitles; public ViewPager mViewPager; private static final int COLOR_TEXT_NORMAL = 0x77FFFFFF; private static final int COLOR_TEXT_HIGHLIGHTCOLOR = 0xFFFFFFFF; private int indicaytor_type; private int indicaytor_type_circle = 1; private int indicaytor_type_triangle = 2; public ViewPagerIndicator(Context context) { this(context, null); } public ViewPagerIndicator(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ViewPagerIndicator); mTabVisibleCount = a.getInt(R.styleable.ViewPagerIndicator_item_count,COUNT_DEFAULT_TAB); indicaytor_type = a.getInt(R.styleable.ViewPagerIndicator_indicaytor_type,indicaytor_type_circle); if (mTabVisibleCount < 0) mTabVisibleCount = COUNT_DEFAULT_TAB; a.recycle(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(Color.parseColor("#ffffffff")); mPaint.setStyle(Style.FILL); //mPaint.setPathEffect(new CornerPathEffect(3)); } @Override protected void onFinishInflate() { super.onFinishInflate(); int cCount = getChildCount(); if (cCount == 0) return; for (int i = 0; i < cCount; i++) { View view = getChildAt(i); LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams(); lp.weight = 0; lp.width = getScreenWidth() / mTabVisibleCount; view.setLayoutParams(lp); } setItemClickEvent(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGEL);// 1/6 of width mTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth); initTriangle(); mInitTranslationX = getWidth() / mTabVisibleCount / 2 - mTriangleWidth/ 2; } @Override protected void dispatchDraw(Canvas canvas) { if(indicaytor_type == indicaytor_type_circle){ canvas.save(); int radius = 6; canvas.translate(mInitTranslationX + mTranslationX, getHeight() - 10); canvas.drawCircle(radius, 0, radius, mPaint); canvas.restore(); }else{ mPaint.setPathEffect(new CornerPathEffect(3)); canvas.save(); canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1); canvas.drawPath(mPath, mPaint); canvas.restore(); } super.dispatchDraw(canvas); } private void initTriangle() { mPath = new Path(); mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2)); mPath.moveTo(0, 0); mPath.lineTo(mTriangleWidth, 0); mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight); mPath.close(); } public interface PageChangeListener { public void onPageScrolled(int position, float positionOffset,int positionOffsetPixels); public void onPageSelected(int position); public void onPageScrollStateChanged(int state); } private PageChangeListener onPageChangeListener; public void setOnPageChangeListener(PageChangeListener pageChangeListener) { this.onPageChangeListener = pageChangeListener; } public void setViewPager(ViewPager mViewPager, int pos) { this.mViewPager = mViewPager; mViewPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { resetTextViewColor(); highLightTextView(position); if (onPageChangeListener != null) { onPageChangeListener.onPageSelected(position); } } @Override public void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) { scroll(position, positionOffset); if (onPageChangeListener != null) { onPageChangeListener.onPageScrolled(position,positionOffset, positionOffsetPixels); } } @Override public void onPageScrollStateChanged(int state) { if (onPageChangeListener != null) { onPageChangeListener.onPageScrollStateChanged(state); } } }); mViewPager.setCurrentItem(pos); highLightTextView(pos); } public void scroll(int position, float offset) { mTranslationX = getWidth() / mTabVisibleCount * (position + offset); int tabWidth = getScreenWidth() / mTabVisibleCount; if (offset > 0 && position >= (mTabVisibleCount - 2) && getChildCount() > mTabVisibleCount) { if (mTabVisibleCount != 1) { this.scrollTo((position - (mTabVisibleCount - 2)) * tabWidth+ (int) (tabWidth * offset), 0); } else { this.scrollTo(position * tabWidth + (int) (tabWidth * offset), 0); } } invalidate(); } protected void highLightTextView(int position) { View view = getChildAt(position); if (view instanceof TextView) { ((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHTCOLOR); } } private void resetTextViewColor() { for (int i = 0; i < getChildCount(); i++) { View view = getChildAt(i); if (view instanceof TextView) { ((TextView) view).setTextColor(COLOR_TEXT_NORMAL); } } } public void setItemClickEvent() { int cCount = getChildCount(); for (int i = 0; i < cCount; i++) { final int j = i; View view = getChildAt(i); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setCurrentItem(j); } }); } } private TextView generateTextView(String text) { TextView tv = new TextView(getContext()); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.width = getScreenWidth() / mTabVisibleCount; tv.setGravity(Gravity.CENTER); tv.setTextColor(COLOR_TEXT_NORMAL); tv.setText(text); tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); tv.setLayoutParams(lp); return tv; } public void setVisibleTabCount(int count) { this.mTabVisibleCount = count; } public void setTabItemTitles(List<String> datas) { if (datas != null && datas.size() > 0) { this.removeAllViews(); this.mTabTitles = datas; for (String title : mTabTitles) { addView(generateTextView(title)); } setItemClickEvent(); } } public int getScreenWidth() { WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } }
http://download.csdn.net/detail/hfreeman2008/8401103
1.Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI
http://blog.csdn.net/lmj623565791/article/details/42160391
2.android viewpager 之 基本使用方法
http://blog.csdn.net/hfreeman2008/article/details/38796449
3.view组件draw,onDraw,dispatchDraw
http://blog.csdn.net/zxxjj/article/details/7478482