Android自定义进度条样式

相信很多人在项目里都想过自定义进度条,不是那种普通的,看看上面的截图,没错,就是这样。前段时间项目刚好需要做这样的进度条,可惜没有什么头绪,思前顾后只有两个方法。

方法一:这张进度条的图片1进度条部分镂空,其他部分显示一个没有透明度的颜色,在该图片里底部放一个底色图片2,图片1和图片2之间放一张宽度为0的图片3,图片3的宽度等于进度*图片1的宽度。通过这样来实现进度条变化的动画;

方法二:进度条图片1进度条部分不镂空,其他部分为空,进度变化时对图片1进行从左到右的垂直颜色变化。

看到这两个方法后相信大家肯定觉得方法二比较好,可是方法二怎么做呢?是的,小编开始也纠结了很久,鉴于网上实现方法二的例子非常少,最后还是采用了方法一;不过方法一有个很致命的缺点,就是图片1非镂空部分不能为有透明度,不然很容易和后面的图片2、3叠加在一起。还好,黄天不负有心人,最后还是实现了方法二。下面我给大家分别细细讲解下方法一和方法二的实现:


方法一:

该方法依赖于布局:这里我弄了一个FrameLayout,这个是我做其他事情需要用到的。该布局需要使用3个view,而且也需要这个进度条镂空才行,镂空后该进度条其余部分必须使用非透明色值。这个是它的缺陷。

<RelativeLayout
        android:id="@+id/lay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/progress_seek_bar"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:layout_marginTop="8dp"
        android:background="@drawable/progress_hud_bg"
        android:paddingBottom="40dp"
        android:paddingLeft="60dp"
        android:paddingRight="60dp"
        android:paddingTop="40dp" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/lay1"
            android:layout_alignLeft="@+id/lay1"
            android:layout_alignRight="@+id/lay1"
            android:layout_alignTop="@+id/lay1"
            android:background="#ffffff" />

        <ImageView
            android:id="@+id/background"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/lay1"
            android:layout_alignLeft="@+id/lay1"
            android:layout_alignTop="@+id/lay1"
            android:background="#26a390" />

        <FrameLayout
            android:id="@+id/lay1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true" >

            <ImageView
                android:id="@+id/spinnerImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/icon_normal" />
        </FrameLayout>
    </RelativeLayout>

其中id为background的这个ImageView宽度设置0,在代码中动态设置他的宽度。

private void init() {
		mImageView = (ImageView) findViewById(R.id.spinnerImageView);
		mBackground = (ImageView) findViewById(R.id.background);

		mimageView = (ImageView) findViewById(R.id.imageview);

		// 绘制完view后取得mImageView的宽度
		ViewTreeObserver vto2 = mImageView.getViewTreeObserver();
		vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
			@SuppressWarnings("deprecation")
			@Override
			public void onGlobalLayout() {
				mImageView.getViewTreeObserver().removeGlobalOnLayoutListener(
						this);
				mWidth = mImageView.getWidth();
			}
		});

		SeekBar progressSeekBar = (SeekBar) findViewById(R.id.progress_seek_bar);

		progressSeekBar.setOnSeekBarChangeListener(this);
	}

	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		// TODO Auto-generated method stub
		// 取得宽度的值
		int bgWidth = (progress * mWidth) / 100;
		// 设置宽度
		RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mBackground
				.getLayoutParams();
		params.width = bgWidth;
		mBackground.setLayoutParams(params);

		// 方法二设置进度
		Bitmap bitmap = setVolume(progress);
		mimageView.setImageBitmap(bitmap);

	}


方法一就不多说,实现很简单,童鞋们就自己去体验了。


方法二:

方法二的处理就灵活多了。

在进入该activity时调用该方法初始化一张bitmap,并复制一张可修改的bitmap。之后我们就以该bitmap进行操作了。

private void initBitmap() {
		// 在这里创建了一张bitmap
		mBitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.normal);
		mBitmap.getConfig();
		// 复制一张可修改的bitmap
		mBitmapCp = mBitmap.copy(Config.ARGB_8888, true);
		// 将这张bitmap设置为背景图片
		BitmapDrawable bd = new BitmapDrawable(mBitmapCp);
		bd.setAntiAlias(true);
		bd.setFilterBitmap(true);

		mBitmapWidth = mBitmap.getWidth();
		mBitmapHeight = mBitmap.getHeight();

	}

之后我们就可以调用setVolume方法,volume是进度。如果童鞋们根据我的步骤做,这时会发现return回来的bitmap有很严重的锯齿,我那时也是卡在这里一段时间。后来我想到一个方法,通过蒙版来处理
// 通过百分比 根据图片宽高算出实际填充宽度
	public int getValue(int volume) {
		return mBitmapWidth - (mBitmapWidth * volume / 100);
	}

	// 修改图片颜色
	@SuppressWarnings("deprecation")
	public Bitmap setVolume(int volume) {
		int startX = 0;
		int endX = 0;

		if (mBackVolume < volume) {
			startX = getValue(volume);
			endX = getValue(mBackVolume);
		}

		// 从左到右填充颜色,如改为for (int i = startX; i < endX; i++) 则为从右到左
		for (int i = mBitmapWidth - endX; i < mBitmapWidth - startX; i++) {
			for (int j = 0; j < mBitmapHeight; j++) {
				// 将需要填充的颜色值如果不是
				// 在这说明一下 如果color 是全透明 或者全黑 返回值为 0
				// getPixel()不带透明通道 getPixel32()才带透明部分 所以全透明是0x00000000
				// 而不透明黑色是0xFF000000 如果不计算透明部分就都是0了
				int color = mBitmapCp.getPixel(i, j);
				if (color != 0) {

					mBitmapCp.setPixel(i, j, 0xff26a390);
				}
			}
		}

		mBackVolume = volume;

		return mBitmapCp;
	}
把上面的return mBitmapCp;改成
Bitmap mask = BitmapFactory.decodeResource(getResources(),
				R.drawable.normal);

		return MaskBitmap(mBitmapCp, mask, mask.getWidth(), mask.getHeight(),
				new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

使用PorterDuffXfermode对图片进行蒙版处理,删去对比原图多出来的部分,并且使用Canvas和Paint,这时我们就可以设置防止锯齿。

/**
	 * 蒙版去除锯齿
	 * 
	 * @param bitmap
	 * @param mask
	 * @param size
	 * @param mode
	 * @return
	 */
	private static Bitmap MaskBitmap(Bitmap bitmap, Bitmap mask, int width,
			int height, Xfermode mode) {
		if (null == bitmap || mask == null) {
			return null;
		}
		// 定义期望大小的bitmap
		Bitmap dstBmp = Bitmap.createBitmap(width, height, Config.ARGB_8888);
		// 定义一个画布
		Canvas canvas = new Canvas(dstBmp);
		// 创建一个取消锯齿画笔
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		// 定义需要绘制的某图片上的那一部分矩形空间
		Rect src = new Rect(0, 0, mask.getWidth(), mask.getHeight());
		// 定义需要将上面的矩形绘制成新的矩形大小
		Rect dst = new Rect(0, 0, width, height);
		// 将蒙版图片绘制成imageview本身的大小,这样从大小才会和UE标注的一样大
		canvas.drawBitmap(mask, src, dst, paint);
		// 设置两张图片的相交模式
		paint.setXfermode(mode);
		// 将src修改为需要添加mask的bitmap大小,因为是要将此bitmap整个添加上蒙版
		src.right = bitmap.getWidth();
		src.bottom = bitmap.getHeight();
		// 在已经绘制的mask上叠加bitmap
		canvas.drawBitmap(bitmap, src, dst, paint);
		return dstBmp;
	}

好,本次讲解基本完成,有什么问题或者不懂的,欢迎留言。

demo下载地址

欢迎大家加我,相互学习,相互讨论

如有转载,请注明出处:http://blog.csdn.net/hjhrq1991


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值