当前位置: 代码迷 >> Android >> android代码兑现ViewPager的indictor效果
  详细解决方案

android代码兑现ViewPager的indictor效果

热度:13   发布时间:2016-05-01 12:52:24.0
android代码实现ViewPager的indictor效果

          今天无聊自己写了一个模仿viewpager的指示器,这个例子是利用我以前写的一片文章的例子进行改进《android横向滚动屏幕特效分析》。

          下面说下我的思路,首先当控件初始化的时候获取ScrollLayout空间的子View控件个数,然后传入我们要写的IndictorView类里面,然后利用onDraw()方法在屏幕上画同等数量的圆形,表示当前屏幕的圆圈我们用不同的颜色区分就行了,然后每次移动的时候我们改变画表示当前屏幕圆圈的位置即可。

          既然要画两种颜色的圆圈那么就要生成两种颜色的画笔,下面是我生成画笔的代码:

/**	 * 生成标识当前屏幕的画笔和背景圆圈的画笔,此方法在构造方法中调用	 */	private void init() {		// 这句是让画笔画得更细腻(抗锯齿)		fontPaint = new Paint(Paint.ANTI_ALIAS_FLAG);		// 这句话的意思是已填充的方式画园,Style.STROKE方式是画一个圆环中间没有填充		fontPaint.setStyle(Style.FILL);		// 设置画笔的颜色		fontPaint.setColor(Color.RED);		backPaint = new Paint(Paint.ANTI_ALIAS_FLAG);		backPaint.setStyle(Style.FILL);		backPaint.setColor(Color.BLACK);	}


        在构造好IndictorView之后我们需要把ScorllView的子元素个数传过来,那么就需要提供一个方法让外部可以把我们需要的数据传如,下面是实现代码:

/**	 * 初始化圆的个数,这里的屏幕宽度是为了后面我们计算圆圈的位置时使用	 * 	 * @param circleNumber	 *            园的数量	 * @param motionWidth	 *            屏幕的宽度	 */	public void init(int circleNumber, float motionWidth) {		this.circleNumber = circleNumber;		this.motionWidth = motionWidth;	}

        现在我们有了园的个数,又得到屏幕的宽度,那么就可以开始画园了,下面是实现代码:

@Override	public void draw(Canvas canvas) {		// 得到圆的Y轴坐标		int height = getHeight() - getPaddingTop() - (radius * 2);		// 这里是根据需要画圆的个数使用一个循环遍历来画园		for (int i = 1; i <= circleNumber; i++) {			// 当当前的圆的下标等于要画的园的下标时候,说明这个下标就是标识当前屏幕下标的园			if (curentCircleNumber == i) {				// 这里的表达式主要是计算园的X轴坐标				canvas.drawCircle((motionWidth - (radius * 2						* (circleNumber - i) + (circlePadding * (circleNumber						- i - 1)))) / 2.0f + 10, height, radius, fontPaint);			} else {				// 画背景圆圈				canvas.drawCircle((motionWidth - (radius * 2						* (circleNumber - i) + (circlePadding * (circleNumber						- i - 1)))) / 2.0f + 10, height, radius, backPaint);			}		}		super.draw(canvas);		// 刷新屏幕		invalidate();	}

      上面就是核心代码,那么有人会问当OnDraw()执行过后怎样改变圆圈的位置能,其实View的onDraw()方法是在这个view被渲染后一直在后台执行的,所以不同担心我们改变curentCircleNumber的值时会不会从绘圆的位置的问题。

      最后大家别忘了一件事,我们在重写空间的时候一定要记得覆盖onMeasure()方法,这里就不多说了,下面是源码:

@Override	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {		setMeasuredDimension(measureWidth(widthMeasureSpec),				measureHeight(heightMeasureSpec));	}	private int measureWidth(int measureSpec) {		int result = 0;		int specMode = MeasureSpec.getMode(measureSpec);		int specSize = MeasureSpec.getSize(measureSpec);		// 当控件设置全屏时		if (specMode == MeasureSpec.EXACTLY) {			result = specSize;		} else {			float temp = circleNumber - 2 * radius;			result = (int) (getPaddingLeft() + getPaddingRight()					+ (circleNumber * 2 * radius) + (circleNumber - 1) * temp + 1);			// 当设置根据内容自动适应			if (specMode == MeasureSpec.AT_MOST) {				result = Math.min(result, specSize);			}		}		return result;	}	private int measureHeight(int measureSpec) {		int result = 0;		int specMode = MeasureSpec.getMode(measureSpec);		int specSize = MeasureSpec.getSize(measureSpec);		// 当空间设置全屏时		if (specMode == MeasureSpec.EXACTLY) {			result = specSize;		} else {			result = (int) (4 * radius + getPaddingTop() + getPaddingBottom() + 1);			// 当设置根据内容自动适应			if (specMode == MeasureSpec.AT_MOST) {				result = Math.min(result, specSize);			}		}		return result;	}

           这时我们的IndictorView类我们就完全写好了,下面是我的布局文件menu.xml:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent" >    <cn.com.karl.scrollview.ScrollLayout        android:id="@+id/scorllView"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:background="@android:color/white" >        <ImageView            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:scaleType="fitCenter"            android:src="@drawable/test1" />        <ImageView            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:scaleType="fitCenter"            android:src="@drawable/test2" />        <ImageView            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:scaleType="fitCenter"            android:src="@drawable/test3" />        <ImageView            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:scaleType="fitCenter"            android:src="@drawable/test1" />            </cn.com.karl.scrollview.ScrollLayout>    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/scorllView"        android:background="#88252525" >        <cn.com.karl.scrollview.IndictorView            android:id="@+id/indictorView"            android:layout_width="fill_parent"            android:layout_height="wrap_content"            android:layout_gravity="center" />    </LinearLayout></RelativeLayout>

          这里值得注意的是android:background="#88252525"这个背景色是为了给我们的IndictorView控件加上透明背景色,这个可以选择性添加。

         下面是主程序使用源码:

package cn.com.karl.activity;import android.app.Activity;import android.os.Bundle;import android.view.Display;import cn.com.karl.R;import cn.com.karl.scrollview.IndictorView;import cn.com.karl.scrollview.ScrollLayout;public class TestScrollLayout extends Activity {	private ScrollLayout scrollLalyout;	private IndictorView indictorView;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.menu);		initView();	}	private void initView() {		scrollLalyout = (ScrollLayout) findViewById(R.id.scorllView);		indictorView = (IndictorView) findViewById(R.id.indictorView);		Display display = getWindowManager().getDefaultDisplay();		indictorView.init(scrollLalyout.getChildCount(), display.getWidth());		scrollLalyout.setIndictorView(indictorView);	}}

           scrollLalyout.setIndictorView(indictorView);这一句是把我们的指示器放到ScrollLayout里面去,当屏幕移动的时候可以调用我们的IndictorView的setCurentCircleNumber()方法来时时改变下标.

          下面是ScrollLayout里面的移动屏幕的方法源码:

/**	 * 移动到下一个屏幕	 * 	 * @param whichScreen	 *            下一个屏幕的下标识	 */	public void snapToScreen(int whichScreen) {		// get the valid layout page		whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));		if (getScrollX() != (whichScreen * getWidth())) {			final int delta = whichScreen * getWidth() - getScrollX();			mScroller.startScroll(getScrollX(), 0, delta, 0, 1000);			mCurScreen = whichScreen;			invalidate(); // Redraw the layout			indictorView.setCurentCircleNumber(whichScreen + 1);		}	}

 

           好了这里就写完了,有不足的地方请大家指正!下面是效果图

  相关解决方案