在自己的项目中,遇到了代码创建ProgressBar,无法更改样式等问题。在交流群里,也有人问过!
今天我就结合我查的资料和大家交流一下。
ProgressBar mProgressBar=new ProgressBar(context);
this.addView(mImageView,0);
这样,可以用代码创建一个ProgressBar,可是怎么把的样式改成横条状呢?
在使用XML文件来布局时,会使用style来设置:
style="?android:attr/progressBarStyleHorizontal"
可是我们有代码怎么来设置呢?没ProgressBar.setStyle()方法啊!
查了一下高手写的文章,了理到从源码中可以看出progressBarStyleHorizontal也是一个布局罢了
源码如下:
<ProgressBar android:layout_width="fill_parent" android:layout_height="wrap_content" android:indeterminateOnly="false" android:progressDrawable="@android:drawable/progress_horizontal" android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal" android:minHeight="20dip" android:maxHeight="20dip" />
我们可以通过代码来设置:
mProgressBar.setIndeterminate(false);
mProgressBar.setProgressDrawable(getResources().getDrawable(android.R.drawable.progress_horizontal));
mProgressBar.setIndeterminateDrawable(getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal));
这样就可以实现ProgressBar的条状布局了!
可这时,我们又会发现ProgressBar的进度,无法刷新
原因是XML文件中的android:indeterminateOnly="false"和 代码中的progressBar.setIndeterminate(false)并不完全一样。布局文件的属性有一个Only结尾但代码中并没有,而查找Api发现并没有setIndeterminateOnly这样的一个方法。
看一下ProgressBar的源码我们会发现ProgressBar中有两个私有变量:mOnlyIndeterminate和mIndeterminate。而程序没有提供设置mOnlyIndeterminate的方法。
这里我们可以使用Java的反射机制来设置。
我们写一个通用的BeanUtils类来进行反射操作:
public class BeanUtils {
private BeanUtils() {
}
/**
* 直接设置对象属性值,无视private/protected修饰符,不经过setter函数.
*/
public static void setFieldValue(final Object object, final String fieldName, final Object value) {
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
Log.e("zbkc", "", e);
}
}
/**
* 循环向上转型,获取对象的DeclaredField.
*/
protected static Field getDeclaredField(final Object object, final String fieldName) {
return getDeclaredField(object.getClass(), fieldName);
}
/**
* 循环向上转型,获取类的DeclaredField.
*/
@SuppressWarnings("unchecked")
protected static Field getDeclaredField(final Class clazz, final String fieldName) {
for (Class superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
// Field不在当前类定义,继续向上转型
}
}
return null;
}
/**
* 强制转换fileld可访问.
*/
protected static void makeAccessible(Field field) {
if (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
field.setAccessible(true);
}
}
}
然后,我们在创建ProgressBar的地方使用下面的语句设置mOnlyIndeterminate为false
BeanUtils.setFieldValue(mProgressBar, "mOnlyIndeterminate", new Boolean(false));
这样就实现了用代码来创建ProgressBar。
下面是我的代码
super(context);
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
ProgressBar mProgressBar=new ProgressBar(context);
BeanUtils.setFieldValue(mProgressBar, "mOnlyIndeterminate", new Boolean(false));
mProgressBar.setIndeterminate(false);
mProgressBar.setProgressDrawable(getResources().getDrawable(android.R.drawable.progress_horizontal));
mProgressBar.setIndeterminateDrawable(getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal));
mProgressBar.setLayoutParams(new FrameLayout.LayoutParams(65, 5, Gravity.CENTER_VERTICAL) );
this.addView(mProgressBar,0);
如果大家有更好的方法,希望大家能给我留言!