android-自定义View-PagerIndicatorView(仿UC浏览区主界面导航)

本文介绍了一种自定义ViewPager指示器的方法,通过重写onDraw方法实现动态绘制导航栏的效果。该指示器能够随着页面滑动改变样式,适用于Android应用中需要平滑过渡指示效果的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处:http://blog.csdn.net/lhlhlh111000/article/details/39472229  (我爱吃鱼的博客)

UC浏览器一直在用,其中有个小控件,感觉看着挺舒服的(或许给我的感觉是有点性感的羡慕);一直想找机会自己写下,刚好这段时间各种不爽,不想做事,所以自己清净下来写了一下;实现比较简单,主体上面是有了,细节上面可能还有待完善。

先来看下要实现的一个效果图:



目标实现就是上图底部略显黑色的导航View;


说下我这边的实现方式:自定义PagerIndicatorView,然后重写onDraw方法,监听页面切换动作,进行绘制左右两个圆角矩形。

private ViewPager mVipTarget;
	
	private OnPageChangeListener mListener;
	
	private Paint mPaint;
	
	private RectF mLeftRect;
	
	private RectF mRightRect;
	
	private int mRound;
	
	private int mItemWidht = 0;
	
	public PagerIndicatorView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mPaint = new Paint();
		mPaint.setStyle(Style.FILL);
		mPaint.setAntiAlias(true);
		
		TypedArray a = context.obtainStyledAttributes(R.styleable.PageIndicatorView);
		int viewColor = a.getColor(R.styleable.PageIndicatorView_viewColor, Color.GRAY);
		mRound = a.getInteger(R.styleable.PageIndicatorView_viewRound, 2);
		a.recycle();
		
		mPaint.setColor(viewColor);
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		if(null == mVipTarget) {
			return;
		}
		
		if(mItemWidht == 0) {
			// 页面总数+1,多出来的一个作为中间空白段
			mItemWidht = getMeasuredWidth()/(mVipTarget.getAdapter().getCount() + 1);
			buildParams(mVipTarget.getCurrentItem(), 0.0f);
		}
		
		// 画左边长度
		canvas.drawRoundRect(mLeftRect, mRound, mRound, mPaint);
		// 画右边长度
		canvas.drawRoundRect(mRightRect, mRound, mRound, mPaint);
		
		super.onDraw(canvas);
	}
	
	/**
	 * 构造参数
	 * @param count
	 */
	private void buildParams(int position, float offset) {
		int paddingTop = getPaddingTop();
		int paddingBottom = getPaddingBottom();
		int viewWidth = getWidth();
		int viewHeight = getHeight();
		int offsetWidht = (int) (offset*mItemWidht + 0.5);
		
		int leftRectRight = (position + 1)*mItemWidht + offsetWidht;
		mLeftRect = new RectF(getPaddingLeft(), paddingTop, 
				leftRectRight, viewHeight - paddingBottom); 
		
		int rightRectLeft = leftRectRight + mItemWidht/2;
		mRightRect = new RectF(rightRectLeft, paddingTop, 
				viewWidth - getPaddingRight(), viewHeight - paddingBottom);
		
	}
	
	/**
	 * 目标ViewPager设置
	 * @param vipTarget
	 */
	public void setViewPager(ViewPager vipTarget) {
		setViewPager(vipTarget, 0);
	}
	
	/**
	 * 目标ViewPager设置
	 * @param vipTarget
	 * @param position
	 */
	public void setViewPager(ViewPager vipTarget, int position) {
		if(null == vipTarget) {
			return;
		}
		
		PagerAdapter adapter = vipTarget.getAdapter();
		if(null == adapter) {
			return;
		}
		int pagerCount = adapter.getCount();
		if(0 == pagerCount) {
			return;
		}
		
		mVipTarget = vipTarget;
		mVipTarget.setOnPageChangeListener(mPageChangeListener);
		mVipTarget.setCurrentItem(position);
	}
	
	public void setOnPageChangeListener(OnPageChangeListener listener) {
		this.mListener = listener;
	}
	
	/**
	 * 颜色设置
	 * @param color
	 */
	public void setColor(int color) {
		mPaint.setColor(color);
		
		invalidate();
	}
	
	private OnPageChangeListener mPageChangeListener = new OnPageChangeListener() {

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

		@Override
		public void onPageSelected(int position) {
			if(null != mListener) {
				mListener.onPageSelected(position);
			}
			
			buildParams(position, 0.0f);
			invalidate();
		}

		@Override
		public void onPageScrollStateChanged(int state) {
			if(null != mListener) {
				mListener.onPageScrollStateChanged(state);
			}
		}
	};
说面下上面的代码,在View初始化的时候创建画笔,作为绘制圆角矩阵用;设置外部ViewPager,并抢占OnPagerChangeListener,完成左右两个圆角矩形的定义;最后调用invalidate方法进行重绘走onDraw方法。

上面就是自定义PagerIndicatorView的实现了,接下来看下使用:

activity_main.xml布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res/com.pig.android.indicator"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/vip_show"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <com.pig.android.indicator.PagerIndicatorView
        android:id="@+id/piv_indicator"
        android:layout_width="24dp"
        android:layout_height="2dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="32dp"
        app:viewColor="#FF4EEE94"
        app:viewRound="0"/>
        
</RelativeLayout>

MainActivity.java文件:


package com.pig.android.indicator;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		initUI(); 
	}
	
	private void initUI() {
		ViewPager vipShow = (ViewPager) findViewById(R.id.vip_show);
		vipShow.setAdapter(new TestAdapter());
		
		PagerIndicatorView pivIndicator = (PagerIndicatorView) findViewById(R.id.piv_indicator);
		pivIndicator.setViewPager(vipShow);
	}
	
	class TestAdapter extends PagerAdapter {
		
		private String[] mColors = new String[] {"#FAF0E6", "#7AC5CD", "#BEBEBE", "#E0FFFF"};
		
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			ImageView imvShow = new ImageView(MainActivity.this);
			imvShow.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
			imvShow.setBackgroundColor(Color.parseColor(mColors[position]));
			container.addView(imvShow);
			return imvShow;
		}
		
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView((View) object);
		}

		@Override
		public int getCount() {
			return 4;
		}

		@Override
		public boolean isViewFromObject(View view, Object object) {
			return view == object;
		}
		
	}
}


以上就是整个demo的实现,这边附上完整的demo下载地址:http://pan.baidu.com/s/1mgqRoiW

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值