Diablo3英雄榜-进度条
目标
- 在发呆的时候添加一个进度条
- 使用第三方控件
- Fragment之间的通信
- Handler的使用
源起
在读取魔兽英雄榜数据的时候,有时候会有很多个网络请求,但是网络的速度永远是无法预估的。这个时候有一个进度条是极好的。我们在前一篇文章中,我们读取了用户信息和用户的装备信息。在读取信息的时候使用了27个Request。这个时候应用有一点点顿。为了让顿的时候有更好的体验,我们加入了一个进度条。我添加了一个第三方控件,用于在等待。做出来的效果是这个样子的。
这个进度条是在英雄列表界面中,我点击了一个英雄之后,他开始读取这个英雄的信息,然后在根据这个英雄读取26件装备的信息。在这个过程中就会随机显示一个图腾,图腾周围有一圈绿色的进度条。因为是读取网络数据,我没有精确的定位进度,所以这个绿条走满之后会切换到下一个图腾,然后继续走进度条。
第三方控件
Android-square-progressbar
在目录中右键->Git Bash
$git clone https://github.com/mrwonderman/android-square-progressbar.git
官方地址:
https://github.com/mrwonderman/android-square-progressbar
Fragment显示进度条
Square_progressbar.xml 代码如下
<FrameLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="#80000000"
xmlns:android="http://schemas.android.com/apk/res/android">
<net.yscs.android.square_progressbar.SquareProgressBar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sprogressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:paddingTop="20dp"
android:layout_gravity="center">
</net.yscs.android.square_progressbar.SquareProgressBar>
</FrameLayout>
ProgressbarFragment 的代码如下:
public class ProgressbarFragment extends Fragment {
OnHeadlineSelectedListener mCallback;
SquareProgressBar mSquareProgressBar;
public static final String ARG_POSITION =
"com.example.lijing.diablo3armory.position";
// 用来存放fragment的Activtiy必须实现这个接口
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// 这是为了保证Activity容器实现了用以回调的接口。如果没有,它会抛出一个异常。
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.square_progressbar, container, false);
mSquareProgressBar = (SquareProgressBar)v.findViewById(R.id.sprogressbar);
Random rm = new Random();
mSquareProgressBar.setImage(mThumbIds[rm.nextInt(mThumbIds.length)]);
int position = (int)getArguments().getInt(ARG_POSITION);
mSquareProgressBar.setProgress(position);
return v;
}
// references to our images
private Integer[] mThumbIds2 = {
R.drawable.barcrest, R.drawable.crscrest,
R.drawable.dhcrest, R.drawable.monkcrest,
R.drawable.wdcrest, R.drawable.widcrest
};
private Integer[] mThumbIds = {
R.drawable.photo1, R.drawable.photo2,
R.drawable.photo3, R.drawable.photo4
};
public void updateArticleView(int position) {
mSquareProgressBar.setProgress(position);
}
}
这个Fragment具有如下功能:
- 随机显示一个图片
- 根据Argument里面的数字来设置进度(这个Fragment是可以跟其他Fragmeng交互的)
如何使用
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragmentContainer, fragment, "progress");
transaction.commit();
在读取完后数据后,比如onResponse()里面,在跳转到其他Fragment之前执行下面的代码
Fragment fragment = getActivity().getSupportFragmentManager().findFragmentByTag("progress");
if(fragment != null)
getActivity().getSupportFragmentManager().beginTransaction().remove(fragment).commit();
这样在点击后退键的时候就不会回到进度条的Fragment里面了。现在就可以正常的显示这个图片了,但是这样做只能显示一个静态的图片。我们需要不停的改变这个控件的进度。因为这个Fragment已经具备了跟其他Fragment交互的条件。
设置进度条的进度
要想使Fragment可以与其他的Fragment可以交互,都必须通过其关联的Activity,而不会跟对方直接通信。我们需要定义一个接口,并在Activity调用该接口。Fragment在onAttach()生命周期方法中获取到接口方法,之后就可以通过调用接口中的方法与Activity进行通信了。
在ProgressbarFragment中,我们做出了如下定义
OnHeadlineSelectedListener mCallback;
……
// 用来存放fragment的Activtiy必须实现这个接口
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
…..
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// 这是为了保证Activity容器实现了用以回调的接口。如果没有,它会抛出一个异常。
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
然后我们就可以
public class MainActivity extends FragmentActivity
implements ProgressbarFragment.OnHeadlineSelectedListener{
….
然后在这个Activity中重写onArticleSelected()
public void onArticleSelected(int position) {
ProgressbarFragment articleFrag = (ProgressbarFragment)
getSupportFragmentManager().findFragmentById(R.id.squareProgressBar1);
if (articleFrag != null) {
articleFrag.updateArticleView(position);
} else {
ProgressbarFragment newFragment = new ProgressbarFragment();
Bundle args = new Bundle();
args.putInt(ProgressbarFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentContainer, newFragment);
transaction.commit();
}
}
这样之后我们可以使用onArticleSelected(0-100)来设置进度条了。
让进度条不停的动
我们需要读取27条信息当然我们可以做成在每个onResponse()里面根据读取的数量之一来设置进度。如果这样做的话还可以在图片上显示数字百分比更好看。我的做法是设置了一个时钟每次随机增加一个数字,当数字大于或等于100后自动归0。这个就涉及到一个时钟的问题。
我采用了handler,首先我先定义了3个变量和一个方法
private Handler handler = new Handler();
private boolean run = true;
private int count = 1;
。。。。。
private Runnable myRunnable= new Runnable() {
public void run() {
Random rm = new Random();
if (run) {
handler.postDelayed(this, 100);
if(count >= 100)
count=1;
else
count += rm.nextInt(50);
onArticleSelected(count);
}
}
};
这样我们就可以使用handler.post(myRunnable);来激活这个handler了。当需要让handler停止的时候,只需要将run = false就可以了。