PorterDuff使用实例----实现新浪微博图片下载效果
先上效果图,如demo_sinaweibo.gif
由效果图,下半部分是简单的效果叠加,上半部分是新浪微博加载图片显示进度的效果,显示进度的半透明区域只与根据背景图的非透明区域叠加,背景图的透明区域仍为透明。
为实现此要求,联想到APIDemos中的com.example.android.apis.graphics.Xfermodes,可以自定义组件在组件的绘制过程中设置PorterDuff.Mode即可实现。
另效果图中显示当下载进度超过50%时,重新设置了背景图。
本次自定义组件选择继承ImageView来实现,名为PorterDuffView。将ImageView新增一porterduffMode。在该模式下,将可显示图片加载进度;否则按ImageView原有规则显示图片。
1.PorterDuffView的XML编码
设置PorterDuffView的porterduffMode,可有两种方式,一为在xml中设置,一为在代码设置。
xml中设置的实现:
在/res/values下新建一"attrs.xml",内容如下:
[html]
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<!--请参阅
[android_sdk]\platforms\android-n\data\res\values\attrs.xml
-->
<declare-styleable name="porterduff.PorterDuffView">
<attr name="porterduffMode" format="boolean"></attr>
</declare-styleable>
</resources>
在此声明中,属性名为"porterduffMode",对其赋值范围为boolean型。赋值范围的规范可参考:[android_sdk]\platforms\android-n\data\res\values\attrs.xml
有声明后,在layout下的布局文件,需首先在原有基础上添加一命名空间,代码如下:
[html]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:porterduff="http://schemas.android.com/apk/res/lab.sodino.porterduff"
android:orientation="vertical"
.... ....
></LinearLayout>
命名空间名为"porterduff",赋值规则为"http://schemas.android.com/apk/res/"+App包名。
在布局文件中使用PorterDuffView时,几乎与ImageView一致,设置porterduffMode如下:
[html]
<lab.sodino.porterduff.PorterDuffView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/porterDuffView"
android:src="@drawable/loading"
android:layout_gravity="center"
porterduff:porterduffMode="true"
></lab.sodino.porterduff.PorterDuffView>
另,在代码中设置porterduffMode为直接调用setPorterDuffMode(boolean),参数为true即可。
2.PorterDuffView的Java编码
需要重写ImageView的onDraw()方法。
当其porterduffMode值为true时,显示图片加载进度。否则按ImageView 的规则显示图片。
由效果图可知,需要生成一半透明的前景图。
生成前景图的代码为:
[java]
/** 生成一宽与背景图片等同高为1像素的Bitmap,。 */
private static Bitmap createForegroundBitmap(int w) {
Bitmap bm = Bitmap.createBitmap(w, FG_HEIGHT, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(FOREGROUND_COLOR);
c.drawRect(0, 0, w, FG_HEIGHT, p);
return bm;
}
为节约内存消耗,生成的前景图Bitmap其高度只有1像素。那么在onDraw()方法中,需要根据加载进度,循环滴绘制叠加区域。代码如下:
[java] view plaincopy
int tH = height - (int) (progress * height);
for (int i = 0; i < tH; i++) {
canvas.drawBitmap(bitmapFg, tmpW, tmpH + i, paint);
}
在onDraw()方法中,调用Paint.setXfermode()绘制完叠加区域后,应再次对其设置值为null取消PorterDuff效果。
加载区域的进度值由PorterDuffView.setProgress()决定,因为每次设定新的进度后,应该调用 invalidate()及时刷新界面。
效果图中进度过50%时更改了背景图,方法为PorterDuffView.setBitmap(),该方法将重新计算Bitmap的宽高,并生成新的前景图,调用ImageView.setImageBitmap()请求对组件重新布局及刷新界面。
本文为Sodino所有,转载请注明出处:http://blog.csdn.net/sodino/article/details/7741236
以下贴出Java代码,XML请看官自行实现:
[java]
ActPorterDuff.java
package lab.sodino.porterduff;
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class ActPorterDuff extends Activity implements OnSeekBarChangeListener {
private SeekBar seekbar;
private PorterDuffView porterDuffView;
private int currentId;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
seekbar = (SeekBar) findViewById(R.id.seekbar);
seekbar.setOnSeekBarChangeListener(this);
float progress = seekbar.getProgress() * 1.0f / seekbar.getMax();
porterDuffView = (PorterDuffView) findViewById(R.id.porterDuffView);
porterDuffView.setProgress(progress);
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
porterDuffView.setProgress(progress * 1.0f / seekbar.getMax());
if (progress > 50 && currentId != R.drawable.loading_2) {
currentId = R.drawable.loading_2;
porterDuffView.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.loading_2));
} else if (progress <= 50 && currentId != R.drawable.loading) {
currentId = R.drawable.loading;
porterDuffView.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.loading));
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
[java]
PorterDuffView.java
package lab.sodino.porterduff;
import java.text.DecimalFormat;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.g
补充:移动开发 , Android ,