使用android ProgressBar和Toast生成一个界面
首先我需要这样一个界面
这个界面是在使用AudioManager.adjustStreamVolume(int streamType, int direction, int flags)显示出来的,记住flags这里传 AudioManager.FLAG_SHOW_UI才会显示
不然只是逻辑上调整了某个流的声音,用户他看不到界面不知道成功与否。
然后我有一个功能界面是和这个一样的,但功能不一样,好吧,我知道android自带的界面并不好看,但这里只是说明原理和方法,美观不予讨论。
这里核心的2个组件就是一个TextView和ProgressBar。如果自定义的话,需要写一个layout来包裹这2个组件 然后当点击一个按钮时显示出来。
让我们在回到android自带的界面中,当他点击一个按钮时,他会弹出来并且隔一会就会自动消失。这个自动消失我觉得很有用,因为用户只需要调整那一会
能看到界面的改变就行了,不需要一直显示,不然还要让用户在点个返回?多么麻烦呢,操作简单才是重要的。
于是我想到了android 自带的toast有这个功能。好的!大方向确定了,就开始写代码吧
逻辑是这样的让用户点击某个按钮时,弹出上面那个界面,然后过一会消失,这里在显示toast的时候还需要调用改变进度条进度的方法。
接下来上代码吧:
// ////////////////////////先生成一个toast和progress界面
pb = new ProgressBar(context, null,
android.R.attr.progressBarStyleHorizontal);
pb.setMax(GameConfig.GameSpeedMax);
pb.setProgress(GameConfig.GameSpeedDefault);
pb.setLayoutParams(new LinearLayout.LayoutParams(
ExtensionLayoutConfig.ProgressBarWidth,
LinearLayout.LayoutParams.WRAP_CONTENT));
toast = Toast.makeText(context,
RFileIDConvert.getString("gameSpeedBarTitle"),
Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 0, 0);
LinearLayout toastView = (LinearLayout) toast.getView();
toastView.setGravity(Gravity.CENTER);
//请注意这里传1是必要的,因为他的textView已经在创建的时候添加进去了,如果你传0
//那么上面会先显示进度条 下面再显示文字,如果你需要的话可以这么做,但我现在需要
//文字在上方 进度条在下面 so 传1
toastView.addView(pb, 1);
下面是给外部调用的2个接口:
/**
* 设置进度
*/
public void setGameSpeedBarProgress(int progress) {
pb.setProgress(progress);
}
/**
* 显示toast
*/
public void gameSpeedBarShow() {
toast.show();
}
出来的效果是这样
发现和原来的相比没那么大气,所以还需要调整下间距,这个简单 我明天再完善它, 大概功能就是这样了。
总结。大家请不要小看这么一个界面,我刚开始也觉得很容易,可实现起来发现的问题也不少。
1.一般布局我习惯用代码布局,但碰到ProgressBar我只能无语。在代码中默认的风格是环形的,在XML布局中默认的是水平的
xml中他默认是这么设置的 <ProgressBar style="?android:attr/progressBarStyleHorizontal"
呵呵,难点出来了,这个如果你想用代码设置的话,告诉你很抱歉没有设置风格的方法。有人会说了ProgressBar 中不是有个setScrollBarStyle(int style)方法么。
那么我请你测试完了在说话。这个方法是无效的,请看API的描述。然后我查源码想找出水平方向风格使用了那些设置接口,
我们可以看下progressBarStyleHorizontal样式中给View设置了哪些属性,我们找到framework下的res目录下的values/Theme.xml文件,搜索progressBarStyleHorizontal会发现如下行:
<item name="progressBarStyleHorizontal">@android:style/Widget.ProgressBar.Horizontal</item>
该主题对应的Widget样式是Widget.ProgressBar.Horizontal,我们在同样的的目录下打开style.xml文件,搜索该样式,可以找到如下代码:
<style name="Widget.ProgressBar.Horizontal">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
<item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item>
<item name="android:minHeight">20dip</item>
<item name="android:maxHeight">20dip</item>
</style>
好了,看到这里告诉你,你可以不使用<item name="progressBarStyleHorizontal">@android:style/Widget.ProgressBar.Horizontal</item>
而使用
android:indeterminateOnly="false"
android:progressDrawable="@android:drawable/progress_horizontal"
android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal"
android:minHeight="20dip"
android:maxHeight="20dip" />
同样可以实现水平进度条。我知道大家都会使用那一行而不使用这么多行。我明白,我只是告诉你原理而已。
好的,你知道我喜欢使用代码布局的,然后走代码路线则是
progressBar.setIndeterminate(false);
progressBar.setProgressDrawable(getResources().getDrawable(android.R.drawable.progress_horizontal));
progressBar.setIndeterminateDrawable(getResources().getDrawable(android.R.drawable.progress_indeterminate_horizontal));
progressBar.setMinimumHeight(20);
结果是ProgressBar确实变成了横条,但并没有显示成进度条的样子,我们仔细对比一下纯Java代码和xml布局文件之间差异,我们发现
android:indeterminateOnly="false"和 progressBar.setIndeterminate(false);
并不完全一样布局文件的属性有一个Only结尾但代码中并没有,我们查找Api发现并没有setIndeterminateOnly这样的一个方法。
我们打开ProgressBar的源代码,找到.setIndeterminate(false) 方法。
我们这时候可以发现Indeterminate和IndeterminateOnly并不是同一个东西,
这时我们应该想的到,只要我们把IndeterminateOnly的值变成false就可以使ProgressBar变成进度条的样式,
我们查找所有的代码,发现并没有提供相应的公开方法来修改该属性的值。
也就是说,我们讨论了那么久发现根本就无法通过纯代码的形式来创建一个水平进度条样式的ProgressBar.
但是。。。某人说可以使用反射改变一个类的私有变量的值。内容比较抽象,这里还是略过吧,因为我发现它必须知道变量名才能反射成功,
但我查询后发现有些版本的变量名是不一样的咧,这个版本用的mIndeterminateOnly,那个版本用的mOnlyIndeterminate(2.2版)
所以这个地方我果断放弃了纯代码布局,使用
ProgressBar pb = new ProgressBar(context, null,android.R.attr.progressBarStyleHorizontal); 安逸了~~~~ 这只是第一个问题哦
2.使用toast的时候需要注意,如果你需要那个背景框就必须makeToast. 如果你喜欢干净的话 可以使用new Toast(context)然后再设置一些属性之类的
如果只想要toast的短暂显示的功能,界面完全自定义的话 推荐使用new Toast(context),最后大家要养成看源码的习惯哦,有时候还是需要自己动手,
丰衣足食啊