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

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。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值