一步一步学android控件(之二十三)—— ProgressBar

来源:互联网 发布:php活动报名系统源码 编辑:程序博客网 时间:2024/05/19 19:34

android中内置了多种风格的ProgressBar(进度条) ,通过style属性设置其样式:

   默认的样式

 圆形稍大一点的ProgressBar , style="?android:attr/progressBarStyleLarge"

   水平的ProgressBar , style="?android:attr/progressBarStyleHorizontal"

我们可以将ProgressBar的样式分为两大类型:

1、圆形动画: 一般用于一些未知“长度”的任务,仅仅表示正在处理任务,但是不知道任务进行到了何处 。

2、水平进度条:一般用于要显示中间进度。条件:知道任务的长度;当前任务完成度。


本文结合两个实例来学习progressBar。

1、定位 + 自定义 圆形动画的 progressBar

       点击“位置服务”时,启动一个线程去加载用户的位置信息,同时显示圆形动画的progressBar。位置信息加载“完成”后发送一个消息更新UI——显示用户位置信息或者显示定位出错信息。

2、文件读取 + 自定义样式的水平progressBar + 文件内容显示

       点击“文件操作”时,启动一个线程读取文件中的信息。所有读取出来的信息,一个字符一个字符的写到TextView中(为了能够清晰的看清楚操作进度 , 每写一个字符线程休眠500毫秒:



下面一步一步实现上述功能。

1、准备一个文件test_file.txt放到assets目录下

中文测试字符。First line .second line .third line .forth line .fifth line .sixth line .seventh line .eighth line .ninth line .tenth line .
2、创建布局文件widget_progressbar_layout.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <Button            android:id="@+id/load_location_btn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@string/str_location_service" />        <Button            android:id="@+id/load_file_btn"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="@string/str_file_op" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="50dp"        android:orientation="horizontal" >        <ProgressBar            android:id="@+id/location_progress_bar"            style="@style/customer_progress_style"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:visibility="invisible" />        <TextView            android:id="@+id/location_text_view"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:visibility="invisible" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="150dp"        android:orientation="vertical" >        <ProgressBar            android:id="@+id/file_reader_progress"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:visibility="invisible"            style="@style/customer_progress_style_horizontal" />        <!-- style="?android:attr/progressBarStyleHorizontal" -->        <TextView            android:id="@+id/file_content_text_view"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:visibility="visible" />    </LinearLayout></LinearLayout>
布局文件中有两个progressBar : 

2.1  自定义圆形动画的progressBar : android:id="@+id/location_progress_bar" 为位置服务的progressBar 其使用了样式 style="@style/customer_progress_style" ,该样式定义在res/values/styles.xml 中

<style name="customer_progress_style" >        <item name="android:indeterminateDrawable">@drawable/progress_style_circle_anim</item>    </style>

style中使用了自定义的drawable ——progress_style_circle_anim.xml , 其内容如下:

<?xml version="1.0" encoding="utf-8"?><rotate xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="500"    android:fromDegrees="0"    android:pivotX="50%"    android:pivotY="50%"    android:repeatCount="-1"    android:repeatMode="reverse"    android:toDegrees="360" >    <shape        xmlns:android="http://schemas.android.com/apk/res/android"        android:dither="true"        android:innerRadiusRatio="4"        android:shape="ring"        android:thicknessRatio="20"        android:useLevel="false" >        <padding            android:bottom="5dp"            android:left="5dp"            android:right="5dp"            android:top="5dp" />        <stroke            android:dashGap="3dp"            android:dashWidth="7dp"            android:color="#FFFF00" />        <gradient            android:centerColor="@color/pregress_style_center_color"            android:centerX="50%"            android:centerY="50%"            android:endColor="@color/pregress_style_end_color"            android:startColor="@color/pregress_style_start_color"            android:type="sweep" />    </shape></rotate>
2.2  自定义水平样式的progressBar : android:id="@+id/file_reader_progress" 为显示文件操作进度的progressBar , 其使用了样式 style="@style/customer_progress_style_horizontal" ,该样式定义在res/values/styles.xml 中

<style name="customer_progress_style_horizontal" parent="android:Widget.ProgressBar.Horizontal">        <item name="android:progressDrawable">@drawable/horizontal_progress_bar_style</item>        <item name="android:indeterminateOnly">false</item>        <item name="android:minHeight">10dip</item><item name="android:maxHeight">10dip</item>    </style>
style中使用自定义的progressDrawable——horizontal_progress_bar_style,其内容如下:

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android" >    <item android:id="@android:id/background">        <shape>            <corners android:radius="3dip" />            <gradient                android:angle="270"                android:centerColor="#ffBBBBBB"                android:centerY="0.75"                android:endColor="#ffCC66FF"                android:startColor="#ffDDDDDD" />        </shape>    </item>    <item android:id="@android:id/secondaryProgress">        <clip>            <shape>                <corners android:radius="3dip" />                <gradient                    android:angle="270"                    android:centerColor="#ffffb600"                    android:centerY="0.75"                    android:endColor="#ffffcb00"                    android:startColor="#ffffd300" />            </shape>        </clip>    </item>    <item android:id="@android:id/progress">        <clip>            <shape>                <corners android:radius="5dip" />                <gradient                    android:angle="90"                    android:centerColor="#ff00ff00"                    android:centerY="0.75"                    android:endColor="#ffffffff"                    android:startColor="#3fF0ff30" />            </shape>        </clip>    </item></layer-list>

3、 创建activity——WidgetProgressBarActivity.java

package com.xy.zt.selfdefinewieget;import android.app.Activity;import android.content.Context;import android.content.res.AssetManager;import android.location.Address;import android.location.Geocoder;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;import org.apache.http.util.EncodingUtils;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.util.List;public class WidgetProgressBarActivity extends Activity implements OnClickListener,        LocationListener {    public static final int MSG_REFRESH_LOCATION_UI = 1;    public static final int MSG_REFRESH_FILE_OP_UI = 2;    private Button mLocationBtn;    private Button mFileBtn;    private ProgressBar mLocationProgress;    private ProgressBar mFileProgress;    private TextView mLcationTv;    private TextView mFileTv;    private LocationManager mLocManager;    private LocationTaskThread mLocationThread;    private FileReaderThread mFileThread;    private Handler mRefreshHandler = new Handler() {        private boolean isProMaxSetted = false;        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MSG_REFRESH_LOCATION_UI:                    mLcationTv.setText((String) msg.obj);                    mLocationProgress.setVisibility(View.GONE);                    mLcationTv.setVisibility(View.VISIBLE);                    mFileBtn.setClickable(true);                    break;                case MSG_REFRESH_FILE_OP_UI:                    Bundle data = msg.getData();                    if (data == null || !data.containsKey(READ_CHARACTOR)) {                        Toast.makeText(WidgetProgressBarActivity.this, (String) msg.obj,                                Toast.LENGTH_SHORT).show();                    } else {                        mFileTv.setVisibility(View.VISIBLE);                        int count, size;                        char charactor;                        count = data.getInt(FILE_READ_LENGTH_KEY);                        size = data.getInt(FILE_LENGTH_KEY);                        charactor = data.getChar(READ_CHARACTOR);                        if (!isProMaxSetted) {                            mFileProgress.setMax(size);                        }                        mFileProgress.setProgress(count);                        mFileProgress.setSecondaryProgress(1 + count);                        mFileTv.setText(mFileTv.getText().toString() + charactor);                        if (count >= size) {                            mLocationBtn.setClickable(true);                        }                    }                    break;            }        }    };    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.widget_progressbar_layout);        init();        mLocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);        try {            mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000l, 0f, this);            mLocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000l, 0f, this);        } catch (IllegalArgumentException e) {        }    }    private void init() {        mFileProgress = (ProgressBar) findViewById(R.id.file_reader_progress);        mLocationProgress = (ProgressBar) findViewById(R.id.location_progress_bar);        mLocationBtn = (Button) findViewById(R.id.load_location_btn);        mLocationBtn.setOnClickListener(this);        mFileBtn = (Button) findViewById(R.id.load_file_btn);        mFileBtn.setOnClickListener(this);        mLcationTv = (TextView) findViewById(R.id.location_text_view);        mFileTv = (TextView) findViewById(R.id.file_content_text_view);    }    public void onClick(View v) {        switch (v.getId()) {            case R.id.load_location_btn:                if (mLocationThread == null || mLocationThread.isThreadEnd) {                    mLocationThread = new LocationTaskThread(this, mLocManager,                            mRefreshHandler.obtainMessage(MSG_REFRESH_LOCATION_UI),                            this);                    mLocationThread.start();                } else {                    Toast.makeText(this,                            "后台线程正在加载位置信息,请稍等 !...",                            Toast.LENGTH_SHORT).show();                    return;                }                mFileProgress.setVisibility(View.GONE);                mFileTv.setVisibility(View.GONE);                mLocationProgress.setVisibility(View.VISIBLE);                mFileBtn.setClickable(false);                break;            case R.id.load_file_btn:                if (mFileThread == null || mFileThread.isTeminated) {                    mFileThread = new FileReaderThread(this,                            mRefreshHandler.obtainMessage(MSG_REFRESH_FILE_OP_UI));                    mFileThread.start();                } else {                    Toast.makeText(this,                            "后台线程正在读取文件信息,请稍等 !...",                            Toast.LENGTH_SHORT).show();                    return;                }                mFileTv.setText("");                mFileProgress.setVisibility(View.VISIBLE);                mFileTv.setVisibility(View.VISIBLE);                mLocationProgress.setVisibility(View.GONE);                mLcationTv.setVisibility(View.GONE);                mLocationBtn.setClickable(false);                break;        }    }    public void onLocationChanged(Location location) {    }    public void onProviderDisabled(String provider) {    }    public void onProviderEnabled(String provider) {    }    public void onStatusChanged(String provider, int status, Bundle extras) {    }    static class LocationTaskThread extends Thread {        LocationManager mLM;        Message mMessage;        LocationListener mLL;        public boolean isThreadEnd;        private Context mContext;        public LocationTaskThread(Context context, LocationManager lm, Message msg,                LocationListener ll) {            mContext = context;            mLM = lm;            mMessage = msg;            mLL = ll;        }        @Override        public void run() {            isThreadEnd = false;            List<Address> curAddress = null;            Location l = mLM.getLastKnownLocation(LocationManager.GPS_PROVIDER);            if (l == null) {                l = mLM.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);            }            if (l == null) {                mMessage.obj = "Get location information failure !...";                mMessage.sendToTarget();                isThreadEnd = true;                return;            } else {                l.getLatitude();                Geocoder coder = new Geocoder(mContext);                for (int i = 0; i < 7; i++) {                    try {                        curAddress = coder.getFromLocation(                                l.getLatitude(),                                l.getLongitude(),                                1);                        if (curAddress != null) {                            break;                        }                    } catch (IOException e) {                        Log.w("WidgetProgressBarActivity", i + " get location failed !...");                    }                }            }            if (curAddress != null) {                Address address = curAddress.get(0);                System.out.println(address.toString());                mMessage.obj = address.toString();                mMessage.sendToTarget();            } else {                mMessage.obj = "Get location address failure !...";                mMessage.sendToTarget();            }            isThreadEnd = true;        }    }    public static final String FILE_LENGTH_KEY = "FileTotalSize";    public static final String FILE_READ_LENGTH_KEY = "ReadCount";    public static final String READ_CHARACTOR = "Charactor";    static class FileReaderThread extends Thread {        private Message mMsg;        private Context mContext;        public boolean isTeminated;        Handler mHandler;        public FileReaderThread(Context context, Message msg) {            mContext = context;            mMsg = msg;            mHandler = mMsg.getTarget();        }        @Override        public void run() {            isTeminated = false;            InputStream is = null;            Bundle data = new Bundle();            try {                AssetManager assets = mContext.getAssets();                is = assets.open("test_file.txt");                int lenByte = is.available();                byte[] buffer = new byte[lenByte];                is.read(buffer);                String str = EncodingUtils.getString(buffer, "utf-8");                int len = str.length();                data.putInt(FILE_LENGTH_KEY, len);                int count = 0;                char charactor;                for (int i = 0; i < len; i++) {                    mMsg = mHandler.obtainMessage(MSG_REFRESH_FILE_OP_UI);                    charactor = str.charAt(i);                    data.putInt(FILE_READ_LENGTH_KEY, ++count);                    data.putChar(READ_CHARACTOR, charactor);                    mMsg.setData(data);                    mMsg.sendToTarget();                    sleep(500);                }            } catch (FileNotFoundException e) {                mMsg.obj = "没有找到您所指定的文件!...";                mMsg.sendToTarget();            } catch (IOException e) {                mMsg.obj = "读取文件数据失败!...";                mMsg.sendToTarget();            } catch (InterruptedException e) {                mMsg.obj = "读取文件数据线程被异常中断!...";                mMsg.sendToTarget();            } finally {                try {                    if (is != null) {                        is.close();                    }                } catch (IOException e) {                }            }            isTeminated = true;        }    }}
代码中没有太多可以说的,只有两点需要注意:

3.1 在文件操作中需要重复的想handler发送消息

for (int i = 0; i < len; i++) {                    mMsg = mHandler.obtainMessage(MSG_REFRESH_FILE_OP_UI);                    charactor = str.charAt(i);                    data.putInt(FILE_READ_LENGTH_KEY, ++count);                    data.putChar(READ_CHARACTOR, charactor);                    mMsg.setData(data);                    mMsg.sendToTarget();                    sleep(500);                }
开始的时候没有添加如下代码

mMsg = mHandler.obtainMessage(MSG_REFRESH_FILE_OP_UI);
mMsg.sendToTarget();结果老是出现NullPointerException 。


3.2 在操作assets目录下的文件时一定要用AssetsManager,使用样例代码如下

AssetManager assets = mContext.getAssets();                is = assets.open("test_file.txt");

4、 老规矩在ViewData.java中添加如下代码(此部分内容可选)

public static final int PROGRESS_BAR_ID = GRID_ID + 1;    public static final String PROGRESS_BAR_NAME = "ProgressBar";private static final ViewData mProgressBar = new ViewData(PROGRESS_BAR_NAME,            PROGRESS_BAR_ID);View_Datas.add(mProgressBar);

在WidgetsAdapter的handleItemClicked方法中添加如下代码
case ViewData.PROGRESS_BAR_ID:                intent.setClass(mContext, WidgetProgressBarActivity.class);                mContext.startActivity(intent);                break;

ProgressBar控件就学到这里,下一个控件RatingBar。