安卓开发之自定义ProgressBar简单完成颜色渐变功能进度条

 更新时间:2016年9月20日 19:53  点击:1589
下面我们一起来看一篇关于安卓开发之自定义ProgressBar简单完成颜色渐变功能进度条的例子,希望文章能够对各位有帮助。

我们在使用电脑或者手机时,经常会遇到进度条,比如下图:

今天我来演示一下,如何做出简单并且漂亮的颜色渐变进度条。

首先我先新建了一个系统默认样式的进度条,代码如下:

运行后显示如下:
大家可以看出,并不是很好看,那么下面开始进行自定义进度条的编写吧!
首先为ProgressBar设置一个drawable,代码如下:
这个代码在哪呢,请回到上面新建系统默认样式进度条时,其中一个属性为  style=”@android:style/Widget.Holo.ProgressBar.Horizontal”这条设置了进度条的style为Widget.Holo.ProgressBar.Horizontal,我们点进去看一下代码,如下图:
,我们看到一条属性为progressDrawable,继续跟上,发现代码如下:
,其中有三个ID,分别为background,secondaryProgress和progress,其中background为进度条的背景,secondaryProgress不清楚何功能,据说是在网上看在线视频的时候,缓冲进度显示的那个灰色的进度条,这里不管,progress为进度条的样子。
我们新建一个名为progress的layer-listXML文件,我们把IDprogress的内容拷贝到progress中,增删其中代码如下:
,主要属性 : 颜色为橙色到橙红色之间的渐变,圆角360dp表示左右两边为半圆.在ProgressBar中引用为:
:运行结果如下:
颜色渐变效果出现了,是不是挺好看的,这只是我自己加的颜色,如果有设计师提供精美图片,那么,还会更美丽。我们在他外面加层RelativeLayout,并设置一个shape,增加美观度,shape名字为shape_progressbar,
shape代码如下:
总代码如下
 
效果如下:

至此,自定义progressbar颜色渐变功能完成!

友盟是一款移动应用统计分析平台。它可以帮助移动应用运营人员统计和分析流量来源、产品留存数据、用户属性和行为数据等,以便产品开发者和运营人员利用数据进行产品、运营、推广策略的决策。

软硬件环境
    Macbook Pro MGX 72
    Android Studio 1.3.2
    Genymotion模拟器


集成友盟SDK

首先到友盟官网http://www.umeng.com/注册个帐户,完成后到管理后台添加需要集成友盟统计的应用,如下

umneg_01

提交后,分给你的应用分配key,如下

umneg_02

接下来到http://dev.umeng.com/analytics/android-doc/sdk-download下载SDK,将下载下来的文件夹中的libs里的jar文件copy到工程中的libs中,在Android Studio中右键单击jar文件,选择Add as library完成导入。


配置AndroidManifest.xml

添加相应权限,如下

<uses-sdk android:minSdkVersion="4"></uses-sdk>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>

然后填写key和渠道id,一个包中只能添加一个渠道,如下

<meta-data android:value="这里填写友盟分配的key值" android:name="UMENG_APPKEY" />
<meta-data android:value="这里填写渠道名称,如Wandoujia或者360" android:name="UMENG_CHANNEL" />

集成代码

在每个Activity的onResume方法中调用MobclickAgent.onResume(Context),在onPause方法中调用MobclickAgent.onPause(Context)。如果Activity之间有继承关系,不要重复添加onResume和onPause方法,否则会出现重复统计,影响统计结果。如果App中有调用Process.kill或者System.exit之类的方法杀死进程,请务必在此之前调用MobclickAgent.onKillProcess(Context)方法,用来保存统计数据。

至此,基本功能已经集成完毕,还是很简单的。后续的一些高级功能,可以根据自己的需求另行添加,官方的文档已经写得很详细了,这里就不再写了,感兴趣的去友盟的官网查看。



友盟统计怎么算新增用户 android

Android 统计分析 SDK使用指南


1. 建立App,下载SDK


登录你的帐号后,看到友盟的管理后台,点击"+添加新应用",进入新应用信息填写的页面。

App建立成功后,可以获得该App的AppKey,以及最新的开发指南和SDK文件。

可在 这里 下载SDK,包含开发文档,demo程序和jar包。

说明:在新应用信息填写中,请尽量填写真实的信息。您可以通过友盟统计分析平台的特性节省重复建立App的时间。
如果您要对App不同的发布渠道进行统计,不需要创建新App,请使用分发渠道分析,通过分发渠道分析,您可以更方便的对比数据。

2. 实现基本的使用基本统计实现本的页面跳转,机型,分辨率,地理位置 …的统计1. 导入umeng-sdk*.jar(简称SDK)下载最新版sdk的zip包,解压将其中的umeng-sdk.jar释放到本地目录,Eclipse用户右键您的工程根目录,选择Properties -> Java Build Path -> Libraries, 然后点击 Add External JARs... 选择指向 Analytics_Android_SDK_*.jar的路径,点击OK,即导入成功。


2. 配置 AndroidManifest.xml

<manifest……><application ……> ……<activity ……/><meta-dataandroid:value="YOUR_APP_KEY"android:name="UMENG_APPKEY"></meta-data><meta-dataandroid:value="Channel ID"android:name="UMENG_CHANNEL"/></application><uses-sdkandroid:minSdkVersion="4"></uses-sdk><uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission><uses-permissionandroid:name="android.permission.INTERNET"></uses-permission><uses-permissionandroid:name="android.permission.READ_PHONE_STATE"></uses-permission><uses-permissionandroid:name="android.permission.READ_LOGS"></uses-permission></manifest>

说明:


META-DATA 用途
UMENG_APPKEY 用来定位该应用程序的唯一性。
UMENG_CHANNEL 用来标注应用推广渠道,区分新用户的来源来查看统计,您可以使用20位以内的英文和数字为渠道定名,替换value中的"Channel ID"。详见渠道统计。
权限 用途
INTERNET(必须) 允许应用程序联网,以便向我们的服务器端发送数据。
READ_PHONE_STATE(必须) 获取用户手机的IMEI,用来唯一的标识用户。(如果您的应用会运行在无法读取IMEI的平板上,我们会将mac地址作为用户的唯一标识,请添加权限: android.permission.ACCESS_WIFI_STATE )
ACCESS_NETWORK_STATE 检测网络状态,友盟SDK 1.6版本新增权限。
READ_LOGS 如果您想获得客户端crash的报告, 需要添加这个权限。具体见【使用错误报告】。
WRITE_EXTERNAL_STORAGE 如果您使用了友盟自动更新提醒功能,需添加这个权限,为了将更新的APK临时存在SD卡里。


3. 添加代码


添加引用: import com.umeng.analytics.MobclickAgent

注册 Activity: 在每个Activity的onResume方法中调用 MobclickAgent.onResume(Context), onPause方法中调用
MobclickAgent.onPause(Context)

publicvoid onResume() { super.onResume(); MobclickAgent.onResume(this);}publicvoid onPause() { super.onPause(); MobclickAgent.onPause(this);}API:public void onResume(Context context)
context 当前Activity的引用,这里请不要将全局的application context传入。
public void onPause(Context context)
context 当前Activity的引用,这里请不要将全局的application context传入。
API说明:
void onResume(Context context)
context 当前Activity引用

void onPause(Context context)
context 当前Activity引用

说明:
方法将会自动地从AndroidManifest.xml文件里读取Appkey。

确保在所有的activity中都调用 MobclickAgent.onResume() 和MobclickAgent.onPause()方法,这两个调用将不会阻塞应用程序的主线程,也不会影响应用程序的性能。

注意如果您的Activity之间有继承或者控制关系请不要同时在父和子Activity中重复添加onPause和onResume方法,否则会造成重复统计(eg.使用TabHost、TabActivity、ActivityGroup时)。

一个应用程序在多个activity之间连续切换时,将会被视为同一个session(启动)。

当用户两次使用之间间隔超过30秒时,将被认为是两个的独立的session(启动),例如用户回到home,或进入其他程序,经过一段时间后再返回之前的应用。

4. 测试


确认所需的权限都已经添加:INTERNET, READ_PHONE_STATE, (READ_LOGS, WRITE_EXTERNAL_STORAGE)

确认APPKEY已经正确的写入Androidmanifest.xml

确认所有的Activity中都调用了onResume和onPause方法

确认测试手机(或者模拟器)已成功连入网络

启动应用程序,几分钟之后您应该已经可以看到相应的报表.

3. 使用错误报告友盟统计分析工具,还可以帮助您捕捉用户在使用应用程序过程中出现的异常退出(FC), 并在应用程序下次启动时将错误报告发送给服务器。
1. 自动捕获异常退出(FC)
在AndroidManifest.xml里面添加权限android.permission.READ_LOGS

在程序的Main Activity(应用程序入口)的onCreate方法里调用MobclickAgent.onError(Context).

publicvoid onCreate(Bundle savedinstanceState) { super.onCreate(savedInstanceState); MobclickAgent.onError(this); ...}API:public void onError(Context context)
context 当前Activity的引用
说明:错误报告包含应用程序版本,操作系统版本和设备型号以及程序出现异常时的Stacktrace,这些数据将帮助您修正应用程序的Bug。
2. 手动发送错误报告如果您自己捕获了程序中的异常,但是依然希望,将这次异常信息发送到友盟的服务器,您可以调用下面的函数。
MobclickAgent.reportError(Context context,String error) API:public void reportError(Context context, String error)
context 当前Activity的引用

error 开发者手动捕获的错误信息
说明:手动发送的异常信息和自动捕获的异常信息一样,都会展示在错误报告面板。

4. 使用自定义事件除了基本统计分析功能外,我们还支持您自定义的事件分析,例如您可以统计游戏中通过不同关卡的人数,广告的点击次数或者视频被播放的次数等等。 使用自定义事件功能请先在网站应用管理后台(设置->编辑自定义事件)中添加相应的自定义事件后,服务器才会对相应的自定义事件请求进行处理。
1. 事件数量统计1. 在您希望跟踪的代码部分,调用如下方法:MobclickAgent.onEvent(Context context, String event_id);API:public void onEvent(Context context, String event_id)
context 当前Activity的引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID。
示例:统计微博应用中“转发"事件发生的次数,那么在“转发"的函数里调用
MobclickAgent.onEvent(this, "Forward") 2. 记录事件的不同属性及取值,调用如下方法:MobclickAgent.onEvent(Context context, String event_id, Map<String,String>; map);API:public voidonEvent(Context context, String event_id, Map map)
context 当前Activity的引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID。

map 为当前事件的属性和取值集合(key-value)
示例:MobclickAgent.onEvent(LoginActivity.this, "sinaLogin");
新浪用户登陆海知笔记

3. 考虑事件在一个属性上的取值,可以调用如下方法:MobclickAgent.onEvent(Context context, String event_id, String label);API:public void onEvent(Context context, String event_id, String label)
context 当前Activity的引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID.

label 事件的一个属性描述
示例:统计游戏中“死亡"事件发生的关卡数,那么可以在死亡的函数里调用
MobclickAgent.onEvent(this, "player_dead","level");2. 事件时长统计有的事件是持续发生的,需要记录其持续的时间,这里提供两种解决方法。
1. 在事件开始和结束时分别调用onEventBegin和 onEventEnd两个函数。MobclickAgent.onEventBegin(Context context, String event_id);...MobclickAgent.onEventEnd(Context context, String event_id);API:public voidonEventBegin(Context context, String event_id)

public void onEventEnd(Context context, String event_id)
context 当前Activity引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID.
public void onEventBegin(Context context, String event_id, String label)

public void onEventEnd(Context context, String event_id, String label)
context 当前Activity引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID.

label 事件的一个属性描述
示例:跟踪播放音乐事件发生的总时间,在音乐播放开始时调用:
MobclickAgent.onEventBegin(this, "music_play");在音乐播放结束时调用:
MobclickAgent.onEventEnd(this, "music_play");2. 跟踪时长的事件包含多个属性,在事件开始和结束时分别调用onKVEventBegin和 onKVEventEnd两个函数MobclickAgent.onKVEventBegin(Context context, String event_id, Map<String,String> map, String ekvFlag);...MobclickAgent.onKVEventEnd(Context context, String event_id, String ekvFlag);API:public void onKVEventBegin(Context context, String event_id, Map map, String ekvFlag)
context 当前Activity引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID.

map 为当前事件的属性和取值集合(key-value)

ekvFlag 事件标示符
public void onKVEventEnd(Context context, String event_id, String ekvFlag)
context 当前Activity引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID

ekvFlag 事件标示符,ekvFlag 和 event_id 一起标示一个唯一事件,并不会被统计;对于同一个事件,在onKVEventBegin和onKVEventEnd 中要传递相同的event_id 和 flag
示例跟踪每种类型的音乐播放了多久,在音乐播放开始时调用
Map<String,String> music = new HashMap<String,String>(); music.put("type", "popular"); music.put("artist", "JJLin"); music.put("User_status", "registered");MobclickAgent.onKVEventBegin(this, "music",music,"m7");在音乐播放结束时调用:
MobclickAgent.onKVEventEnd(this, "music",music,"m7");3. 自己计算并上传event时长,在您想跟踪时长的代码部分,调用如下方法:MobclickAgent.onEventDuration(Context context, String event_id, long duration);orMobclickAgent.onEventDuration(Context context, String event_id,String label, long duration)orMobclickAgent.onEventDuration(Context context, String event_id, Map<String, String> map, long duration)API:public void onEventDuration(Context context, String event_id, long duration)

public void onEventDuration(Context context, String event_id,String label, long duration)
context 当前Activity引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID

label 事件的一个属性描述

duration 事件持续时长,单位毫秒,您需要手动计算并传入时长,作为事件的时长参数
public void onEventDuration(Context context, String event_id, Map map, long duration)
context 当前Activity引用

event_id 为当前统计的事件ID,注意要先在友盟网站上注册此事件ID

map 为当前事件的属性和取值集合(key-value)

duration 事件持续时长,单位毫秒,您需要手动计算并传入时长,作为事件的时长参数
说明
时长是友盟统计的一个新功能,使用过程中可能会出现一些常见的错误,开发者应该尽量的避免,这里有一些可能出错的案例。

每个event的key不能超过10个,event ID、map中key和value都不能使用特殊字符,且长度不能超过255个字符(否则将截取前255个字符),“id", “ts", “du"是保留字段,不能作为event ID及key的名称

5. 使用分发渠道分析有时需要统计应用程序的分发渠道,例如有多少用户来从联想乐园下载了您的应用,又有多少用户通过Google android market下载到您的应用程序。您只需要在AndroidManifest.xml里添加meta-data,并将 value属性修改为对应的发布渠道名。
配置AndroidManifest.XML添加下面代码
<application ……><activity ……/><meta-dataandroid:value="Channel ID"android:name="UMENG_CHANNEL"/></application>当然,这需要您在不同渠道发布应用程序时,重新编译打包。
说明
不要改变'UMENG_CHANNEL',修改'Channel ID'为您的渠道名称,注意不能是纯数字(eg.value="AndroidMarket")。

每台设备只记录第一次统计到的渠道,您如果在测试的时候发现渠道统计到的设备数量不增加,很可能是因为您用同一个设备修改过渠道号,您换一台设备测试即可。

6. 使用在线配置功能这个功能目前可以帮你在网站上动态配置两种类型的参数:

自定义key-value型的键值对

数据发送策略

在程序的入口Activity的OnCreate()方法中调用
publicvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MobclickAgent.updateOnlineConfig(this);}API:public voidupdateOnlineConfig(Context context)

报错UTF-8+BOM我们知道是文件头有空格或一些字符所导致了,对于这个问题我们只需要通过记事本或一些编辑器即可解决,具体操作如下。
今天在用Android studio运行程序的时候,突然报了一种从未见过的错误,如图:

然后我就clean和build,结果都不好使,程序仍然报错,我请教了身边的大神,结果也没见过这种奇葩的情况,最后通过查询网上的解决办法及自己的总结,现整理出一套完美的解决方案。

错误原因,代码编码格式错误,平常我们都用UTF-8格式,之所以报上述错误,是因为编码格式变成了UTF-8+BOM格式,而以前我们编写Android程序都是用eclipse来写,eclipse可以自动把UTF-8+BOM格式转换成UTF-8格式,而Android studio没有这种功能。所以这种错误并不常见。
首先:打开Android studio的设置,把编码格式全部设置成UTF-8格式,此刻你可以试试是否还报错,我的结果是仍然没有解决。
其次,我们需要第三方软件,这里就用editplus来演示解决办法。安装完editplus之后打开软件,然后在里面打开报错的java文件,在菜单栏里点击Document命令,选择File Encoding——Convert Encoding,如图:

image

弹出Convert Encoding对话框,这时我们可以看到编码格式就是UTF-8+BOM,然后我们把它改成UFT-8就可以了,如图:imag2e

再去Android studio运行程序,就不会再报错了

在Android应用开发中,ListView数据的刷新经常用,我们都熟悉,如果我们在ListView实现Item局部刷新,刷新的同时实现下载进度条局部更新呢?本文来告诉你。

对于ListView数据的刷新大家都知道,改变Adapter的数据源,然后调用Adapter的notifyDateSetChanged()方法即可。

但是在做公司项目的时候,有个下载模块,因为可能同时下载好几个数据,所以用的listview展示所有正在下载的内容。因为下载进度要实时更新,所以要不停的调用notifyDateSetChanged刷新数据。这样会不停的重新绘制整个listview的界面,性能开销非常大。而且如果每个item有图片的话,每个item的图片都需要重新加载,就算图片做了内存缓存,刷新一下图片也会闪一下,不停的刷新就会导致各个item的图片不停的闪,体验一点都不好。

那么对于上面问题,有没有解决办法呢?当然是有的。我们可以针对某一个item进行局部更新,而不影响其它没有修改的item。那么具体如何实现的呢?我们看下面的代码。

private void updateView(int itemIndex) {
    //得到第一个可显示控件的位置,
    int visiblePosition = mListView.getFirstVisiblePosition();
    //只有当要更新的view在可见的位置时才更新,不可见时,跳过不更新
    if (itemIndex - visiblePosition >= 0) {
        //得到要更新的item的view
        View view = mListView.getChildAt(itemIndex - visiblePosition);
        //调用adapter更新界面
        mAdapter.updateView(view, itemIndex);
    }
}

这个函数主要是根据传入的itemIndex来获取第itemIndex的数据所显示的view。itemIndex就是要修改的数据再List集合中的位置,比如我这里下载进度有更新,发了一个广播这里接收到了,需要修改该下载内容的进度条,广播接收器可以这么写:

@Override
public void onReceive(Context context, Intent intent) {
    AppContent appContent = intent.getParcelableExtra("appContent");
    if(appContent == null) return;
    int itemIndex = 0;
    for(AppContent appContent1 : mList) {
        if(appContent.getUrl().equals(appContent1.getUrl())) {
            itemIndex = mList.indexOf(appContent1);
            appContent1.setDownloadPercent(appContent.getDownloadPercent());
            break;
        }
    }
    updateView(itemIndex);
}

下面看Adapter的具体代码:

public class AppContentAdapter extends BaseAdapter{

    private List<AppContent> mDates = null;
    private Context mContext;

    public AppContentAdapter(Context context) {
        this.mContext = context;
    }

    @Override
    public int getCount() {
        return mDates.size();
    }

    @Override
    public Object getItem(int position) {
        return mDates.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void setDates(List<AppContent> mDates) {
        this.mDates = mDates;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.listitem_download, null);
            holder.statusIcon = (DownloadPercentView) convertView.findViewById(R.id.status_icon);
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.downloadPercent = (TextView) convertView.findViewById(R.id.download_percent);
            holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progressbar);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        setData(holder, position);
        return convertView;
    }

    /**
     * 设置viewHolder的数据
     * @param holder
     * @param itemIndex
     */
    private void setData(ViewHolder holder, int itemIndex) {
        AppContent appContent = mDates.get(itemIndex);
        holder.name.setText(appContent.getName());
        holder.progressBar.setProgress(appContent.getDownloadPercent());
        setIconByStatus(holder.statusIcon, appContent.getStatus());
        if(appContent.getStatus() == AppContent.Status.PENDING) {
            holder.downloadPercent.setVisibility(View.INVISIBLE);
        } else {
            holder.downloadPercent.setVisibility(View.VISIBLE);
            holder.statusIcon.setProgress(appContent.getDownloadPercent());
            holder.downloadPercent.setText("下载进度:" + appContent.getDownloadPercent() + "%");
        }
    }


    /**
     * 局部刷新
     * @param view
     * @param itemIndex
     */
    public void updateView(View view, int itemIndex) {
        if(view == null) {
            return;
        }
        //从view中取得holder
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.statusIcon = (DownloadPercentView) view.findViewById(R.id.status_icon);
        holder.name = (TextView) view.findViewById(R.id.name);
        holder.downloadPercent = (TextView) view.findViewById(R.id.download_percent);
        holder.progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
        setData(holder, itemIndex);
    }

    /**
     * 根据状态设置图标
     * @param downloadPercentView
     * @param status
     */
    private void setIconByStatus(DownloadPercentView downloadPercentView, AppContent.Status status) {
        downloadPercentView.setVisibility(View.VISIBLE);
        if(status == AppContent.Status.PENDING) {
            downloadPercentView.setStatus(DownloadPercentView.STATUS_PEDDING);
        }
        if(status == AppContent.Status.DOWNLOADING) {
            downloadPercentView.setStatus(DownloadPercentView.STATUS_DOWNLOADING);
        }
        if(status == AppContent.Status.WAITING) {
            downloadPercentView.setStatus(DownloadPercentView.STATUS_WAITING);
        }
        if(status == AppContent.Status.PAUSED) {
            downloadPercentView.setStatus(DownloadPercentView.STATUS_PAUSED);
        }
        if(status == AppContent.Status.FINISHED) {
            downloadPercentView.setStatus(DownloadPercentView.STATUS_FINISHED);
        }
    }

    private class ViewHolder {
        private DownloadPercentView statusIcon;
        private TextView name;
        private TextView downloadPercent;
        private ProgressBar progressBar;
    }
}


ListView中 局部刷新Item 实现下载进度条局部更新

当更新当前正在下载的任务的时候,使用 notifyDataSetChanged();方法会使整个页面都会刷新。

而且进度更新比较频繁,这就造成了内存的消耗和页面卡顿(在进度更新很频繁的情况),笔者甚至出现了卡住页面无法进行操作的情况。

所以想到了能不能局部刷新某个Item。也查了下资料,问题解决。

解决思路:

通过listview.getFirstVisiblePosition()方法获取到显示的item的首个位置 ,再根据position, 计算出view的位置。获取到具体的view后,对view进行操作,就能够实现局部刷新了。

关键代码:

 public void updateView(int itemIndex) {  
        //得到第一个可显示控件的位置,  
        int visiblePosition = mListView.getFirstVisiblePosition();  
        //只有当要更新的view在可见的位置时才更新,不可见时,跳过不更新  
        if (itemIndex - visiblePosition >= 0) {  
            //得到要更新的item的view  
            View view = mListView.getChildAt(itemIndex - visiblePosition);  
            //从view中取得holder  
            ViewHolder holder = (ViewHolder) view.getTag();  

            HashMap<String, Object> item = data.get(itemIndex);  
            //获取到具体的控件,
            holder.name = (TextView) view.findViewById(R.id.name);  
            holder.process = (ProcessBar) view.findViewById(R.id.process);  
            .......
            //对控件进行操作
            holder.process.setMax(item.get("max"));
            holder.process.setProgress(item.get("progress"));
            ......
     
        }         
    } 

AutoCompleteTextView就是类是百度搜索引擎中的一个下拉框了,就是我们输入内容时自动匹配内容出来了,下面我们一起来看看小编整理的例子。
我们在使用各种搜索引擎的搜索功能时,只需要输入一部分内容,就会显示出后续内容,比如,我们输入一个“1”,下面就会出现”12306″,”123″,”126″等等的提示内容,我们可以快捷选择自己想要搜索的内容进行搜索.如下图:

今天我所写的只是一个简单的,不连接数据库,不访问网络的一个输入提示框,方法如下:

第一步:建立XML文件并照下图编写代码:

图中的 android:completionThreshold=”1″代表我们输入几个字符时才会提示,设置为2的话,我们需要输入两个字符才会提示后面的内容.

第二步:在Activity中编写如下代码:

第三部:运行模拟器:

可以看出,成功的完成了输入提示功能,但是这只是最简单的,后续如果项目需要,还需要做更多复杂的操作,如界面优化等,Android的道路还很远,我和大家一起努力!

上面是一个规定的并没有词库的,下面升级一下。

下面先上我写的代码:

import android.app.Activity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;

public class Read_historyActivity extends Activity implements
  OnClickListener {
 private AutoCompleteTextView autoTv;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  autoTv = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
  initAutoComplete("history",autoTv);
  Button search = (Button) findViewById(R.id.button1);
  search.setOnClickListener(this);
 }
 @Override
 public void onClick(View v) {
  // 这里可以设定:当搜索成功时,才执行保存操作
  saveHistory("history",autoTv);
 }

 /**
  * 初始化AutoCompleteTextView,最多显示5项提示,使
  * AutoCompleteTextView在一开始获得焦点时自动提示
  * @param field 保存在sharedPreference中的字段名
  * @param auto 要操作的AutoCompleteTextView
  */
 private void initAutoComplete(String field,AutoCompleteTextView auto) {
  SharedPreferences sp = getSharedPreferences("network_url", 0);
  String longhistory = sp.getString("history", "nothing");
  String[]  hisArrays = longhistory.split(",");
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_dropdown_item_1line, hisArrays);
  //只保留最近的50条的记录
  if(hisArrays.length > 50){
   String[] newArrays = new String[50];
   System.arraycopy(hisArrays, 0, newArrays, 0, 50);
   adapter = new ArrayAdapter<String>(this,
     android.R.layout.simple_dropdown_item_1line, newArrays);
  }
  auto.setAdapter(adapter);
  auto.setDropDownHeight(350);
  auto.setThreshold(1);
  auto.setCompletionHint("最近的5条记录");
  auto.setOnFocusChangeListener(new OnFocusChangeListener() {
   @Override
   public void onFocusChange(View v, boolean hasFocus) {
    AutoCompleteTextView view = (AutoCompleteTextView) v;
    if (hasFocus) {
      view.showDropDown();
    }
   }
  });
 }

 

 /**
  * 把指定AutoCompleteTextView中内容保存到sharedPreference中指定的字符段
  * @param field  保存在sharedPreference中的字段名
  * @param auto  要操作的AutoCompleteTextView
  */
 private void saveHistory(String field,AutoCompleteTextView auto) {
  String text = auto.getText().toString();
  SharedPreferences sp = getSharedPreferences("network_url", 0);
  String longhistory = sp.getString(field, "nothing");
  if (!longhistory.contains(text + ",")) {
   StringBuilder sb = new StringBuilder(longhistory);
   sb.insert(0, text + ",");
   sp.edit().putString("history", sb.toString()).commit();
  }
<SPAN style="BACKGROUND-COLOR: rgb(240,240,240); FONT-FAMILY: monospace; WHITE-SPACE: pre"> }
}</SPAN>

     上面的代码我实现了autocomplettextview的从sharepreference中读取历史记录并显示的功能,当没有任何输入时,提示最新的5项历史记录(这里可以加个条件,当有历史记录时才显示)
              补上布局的代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <TextView android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/hello" />
 <LinearLayout android:layout_width="0px"
  android:layout_height="0px" android:focusable="true"
  android:focusableInTouchMode="true"></LinearLayout>
 <AutoCompleteTextView
  android:hint="请输入文字进行搜索" android:layout_height="wrap_content"
  android:layout_width="match_parent"
  android:id="@+id/autoCompleteTextView1">
 </AutoCompleteTextView>
 <Button android:text="搜索" android:id="@+id/button1"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"></Button>
</LinearLayout>

   当之有一个edittext或者auto的时候,进入画面时是默认得到焦点的,要想去除焦点,可以在auto之前加一个o像素的layout,并设置他先得到焦点。


下面出现的是源码内容

 需要注意的是,我这里用到的AutoCompleteTextView的几个方法

1. setAdapter()方法:这里要传递的adapter参数必须是继承ListAdapter和Filterable的,其中arrayAdapter和simpleAdapter都能满足要求,我们常用arrayAdapter,因为他不需要像simpleAdapte那样设置他的显示位置和textview组件。
               要想掌握它,就必须查看他的源码,我们可以看看arrayadapter是如何实现
              凡是继承了Filterable的adapter都必须重写getFilter接口方法

    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }          这个filter 就是实现过滤方法的对象,同样,我们可以查看他的源码是如何实现的
          

 /**
     * <p>An array filter constrains the content of the array adapter with
     * a prefix. Each item that does not start with the supplied prefix
     * is removed from the list.</p>
     */
    private class ArrayFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();

            if (mOriginalValues == null) {
                synchronized (mLock) {
                    mOriginalValues = new ArrayList<T>(mObjects);
                }
            }

            if (prefix == null || prefix.length() == 0) {
                synchronized (mLock) {
                    ArrayList<T> list = new ArrayList<T>(mOriginalValues);
                    results.values = list;
                    results.count = list.size();
                }
            } else {
                String prefixString = prefix.toString().toLowerCase();

                final ArrayList<T> values = mOriginalValues;
                final int count = values.size();

                final ArrayList<T> newValues = new ArrayList<T>(count);

                for (int i = 0; i < count; i++) {
                    final T value = values.get(i);
                    final String valueText = value.toString().toLowerCase();

                    // First match against the whole, non-splitted value
                    if (valueText.startsWith(prefixString)) {
                        newValues.add(value);
                    } else {
                        final String[] words = valueText.split(" ");
                        final int wordCount = words.length;

                        for (int k = 0; k < wordCount; k++) {
                            if (words[k].startsWith(prefixString)) {
                                newValues.add(value);
                                break;
                            }
                        }
                    }
                }

                results.values = newValues;
                results.count = newValues.size();
            }

            return results;
        }
          这是arrayAdapter自定义的一个私有内部类,所谓私有,就意味着你不能通过继承去修改这种过滤方法,同样你也不能直接得到他过滤后结果集results。假如你想使用新的过滤方法,你必须重写getfilter()方法,返回的filter对象是你要新建的filter对象(在里面包含performFiltering()方法重新构造你要的过滤方法)
         
         2.setDropDownHeight方法 ,用来设置提示下拉框的高度,注意,这只是限制了提示下拉框的高度,提示数据集的个数并没有变化
         3.setThreshold方法,设置从输入第几个字符起出现提示
         4.setCompletionHint方法,设置提示框最下面显示的文字
         5.setOnFocusChangeListener方法,里面包含OnFocusChangeListener监听器,设置焦点改变事件
         6.showdropdown方法,让下拉框弹出来
        

        我没有用到的一些方法列举
1.clearListSelection,去除selector样式,只是暂时的去除,当用户再输入时又重新出现
2.dismissDropDown,关闭下拉提示框
3.enoughToFilter,这是一个是否满足过滤条件的方法,sdk建议我们可以重写这个方法
4. getAdapter,得到一个可过滤的列表适配器
5.getDropDownAnchor,得到下拉框的锚计的view的id
6.getDropDownBackground,得到下拉框的背景色
7.setDropDownBackgroundDrawable,设置下拉框的背景色
8.setDropDownBackgroundResource,设置下拉框的背景资源
9.setDropDownVerticalOffset,设置下拉表垂直偏移量,即是list里包含的数据项数目
10.getDropDownVerticalOffset ,得到下拉表垂直偏移量
11..setDropDownHorizontalOffset,设置水平偏移量
12.setDropDownAnimationStyle,设置下拉框的弹出动画
13.getThreshold,得到过滤字符个数
14.setOnItemClickListener,设置下拉框点击事件
15.getListSelection,得到下拉框选中为位置
16.getOnItemClickListener。得到单项点击事件
17.getOnItemSelectedListener得到单项选中事件
18.getAdapter,得到那个设置的适配器

[!--infotagslink--]

相关文章

  • C#创建自定义控件及添加自定义属性和事件使用实例详解

    这篇文章主要给大家介绍了关于C#创建自定义控件及添加自定义属性和事件使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-25
  • 解决echarts 一条柱状图显示两个值,类似进度条的问题

    这篇文章主要介绍了解决echarts 一条柱状图显示两个值,类似进度条的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-20
  • JS实现自定义简单网页软键盘效果代码

    本文实例讲述了JS实现自定义简单网页软键盘效果。分享给大家供大家参考,具体如下:这是一款自定义的简单点的网页软键盘,没有使用任何控件,仅是为了练习JavaScript编写水平,安全性方面没有过多考虑,有顾虑的可以不用,目的是学...2015-11-08
  • jQuery实现简单的文件上传进度条效果

    本文实例讲述了jQuery实现文件上传进度条效果的代码。分享给大家供大家参考。具体如下: 运行效果截图如下:具体代码如下:<!DOCTYPE html><html><head><meta charset="utf-8"><title>upload</title><link rel="stylesheet...2015-11-24
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • ant design中upload组件上传大文件,显示进度条进度的实例

    这篇文章主要介绍了ant design中upload组件上传大文件,显示进度条进度的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-29
  • jquery实现模拟百分比进度条渐变效果代码

    本文实例讲述了jquery实现模拟百分比进度条渐变效果代码。分享给大家供大家参考,具体如下:这里为了便于看到加载百分比,对代码进行了处理,实际使用时并不需要这样。运行效果截图如下:在线演示地址如下:http://demo.jb51.net...2015-10-30
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • 自定义jquery模态窗口插件无法在顶层窗口显示问题

    自定义一个jquery模态窗口插件,将它集成到现有平台框架中时,它只能在mainFrame窗口中显示,无法在顶层窗口显示. 解决这个问题的办法: 通过以下代码就可能实现在顶层窗口弹窗 复制代码 代码如下: $(window.top.documen...2014-05-31
  • 自定义feignClient的常见坑及解决

    这篇文章主要介绍了自定义feignClient的常见坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-20
  • pytorch 自定义卷积核进行卷积操作方式

    今天小编就为大家分享一篇pytorch 自定义卷积核进行卷积操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-06
  • PHP YII框架开发小技巧之模型(models)中rules自定义验证规则

    YII的models中的rules部分是一些表单的验证规则,对于表单验证十分有用,在相应的视图(views)里面添加了表单,在表单被提交之前程序都会自动先来这里面的规则里验证,只有通过对其有效的限制规则后才能被提交,可以很有效地保证...2015-11-24
  • jquery自定义插件开发之window的实现过程

    这篇文章主要介绍了jquery自定义插件开发之window的实现过程的相关资料,需要的朋友可以参考下...2016-05-09
  • C#实现带进度条的ListView

    这篇文章主要介绍了C#实现带进度条的ListView 的相关资料,需要的朋友可以参考下...2020-06-25
  • nodejs 终端打印进度条实例代码

    本篇文章主要介绍了nodejs 终端打印进度条实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...2017-04-27
  • PHP的APC模块实现上传进度条

    APC模块,它的全称是Alternative PHP Cache。APC可以将所有PHP代码会被缓存起来, 另外它可提供一定的内存缓存功能.但是这个功能并不是十分完美,有报告说如果频繁使用APC缓存的写入功能,会导致不可预料的错误.如果想使用...2015-10-30
  • Bootstrap进度条组件知识详解

    在网页中,经常见到进度条效果,那么这些个性的进度条组件效果是怎么实现的呢,下面脚本之家小编给大家分享Bootstrap进度条组件知识详解,感兴趣的朋友要求学习吧...2016-05-04
  • php使用APC实现实时上传进度条功能

    php不具备实时上传进度条功能,如果想有这种功能我们一般会使用ajax来实现,但是php提供了一个apc,它就可以与php配置实现上传进度条功能。 主要针对的是window上的应用。 1.服务器要支持apc扩展,没有此扩展的话,下载一个扩...2015-10-30
  • C#自定义事件监听实现方法

    这篇文章主要介绍了C#自定义事件监听实现方法,涉及C#事件监听的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • Vue 组件复用多次自定义参数操作

    这篇文章主要介绍了Vue 组件复用多次自定义参数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27