026 Android 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+读取内存空间、手机进程信息+常驻悬浮框
1.目标效果
带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目)+常驻悬浮框
2.页面布局文件
(1)activity_process_manager.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".ProcessManagerActivity"> <TextView style="@style/TitleStyle" android:text="进程管理" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5dp"> <TextView android:id="@+id/tvPM_process_number" android:text="进程总数" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tvPM_memory_info" android:layout_alignParentRight="true" android:text="剩余/总共" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout> <!--利用帧布局实现常驻悬浮框的效果(需要配合java后台代码)--> <FrameLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <!--让listview占满页面的剩余部分--> <ListView android:id="@+id/lv_process_manager" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> <TextView android:background="#ccc" android:id="@+id/tv_des" android:textColor="#000" android:textSize="18dp" android:layout_width="match_parent" android:layout_height="wrap_content"/> </FrameLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btPM_all_select" android:text="全选" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <Button android:id="@+id/btPM_reverse_select" android:text="反选" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <Button android:id="@+id/btPM_setting" android:text="设置" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> </LinearLayout> </LinearLayout>
(2)listview_process_manager_item_title
<?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="wrap_content"> <TextView android:padding="5dp" android:id="@+id/tvAM_title" android:text="标题" android:textColor="#000" android:background="@color/gray" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
(3)listview_process_manager_item.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5dp"> <ImageView android:id="@+id/iv_app_icon" android:layout_centerVertical="true" android:background="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_marginTop="5dp" android:id="@+id/tvLV_name" android:text="应用名称" android:textColor="#000000" android:textSize="18dp" android:layout_toRightOf="@+id/iv_app_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tvLV_memory_info" android:text="占用内存大小" android:textColor="#000000" android:layout_marginTop="10dp" android:textSize="18dp" android:layout_below="@+id/tvLV_name" android:layout_toRightOf="@+id/iv_app_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <CheckBox android:id="@+id/cb_process_manager" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:clickable="false" android:focusableInTouchMode="false" android:focusable="false" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
3.java后台代码
package com.example.administrator.test62360safeguard; import android.annotation.SuppressLint; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.format.Formatter; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.example.administrator.test62360safeguard.Entity.AppInfoBean; import com.example.administrator.test62360safeguard.Entity.ProcessInfoBean; import com.example.administrator.test62360safeguard.engine.AppInfoProvider; import com.example.administrator.test62360safeguard.engine.ProcessInfoProvider; import java.util.ArrayList; import java.util.List; public class ProcessManagerActivity extends AppCompatActivity { private TextView tvPM_process_number; private TextView tvPM_memory_info; private ListView lv_process_manager; Button btPM_all_select; Button btPM_reverse_select; Button btPM_setting; List<ProcessInfoBean> processInfoList; List<ProcessInfoBean> systemProcessInfoList; List<ProcessInfoBean> customerProcessInfoList; @SuppressLint("HandlerLeak") Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { lv_process_manager.setAdapter(new MyAdapter()); if(customerProcessInfoList!=null){ tv_des.setText("用户进程("+customerProcessInfoList.size()+")"); } } }; private TextView tv_des; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_process_manager); initUI(); initTitleData(); initList(); } private void initList() { lv_process_manager = findViewById(R.id.lv_process_manager); new Thread(){ @Override public void run() { processInfoList = ProcessInfoProvider.getProcessInfo(getApplicationContext()); systemProcessInfoList = new ArrayList<>(); customerProcessInfoList = new ArrayList<>(); for (ProcessInfoBean processInfoBean : processInfoList) { if(processInfoBean.isSystem){ //系统进程 systemProcessInfoList.add(processInfoBean); }else { //用户进程 customerProcessInfoList.add(processInfoBean); } } handler.sendEmptyMessage(0); } }.start(); } private void initTitleData() { int processCount = ProcessInfoProvider.getProcessCount(this); tvPM_process_number.setText("进程总数:"+processCount); //获取可用内存大小,并且格式化 long availSpace = ProcessInfoProvider.getAvailSpace(this); String availSpaceStr = Formatter.formatFileSize(this, availSpace); //获取运行内存大小,并且格式化 long totalSpace = ProcessInfoProvider.getTotalSpace(this); String totalSpaceStr = Formatter.formatFileSize(this, totalSpace); tvPM_memory_info.setText("剩余/总共:"+availSpaceStr+"/"+totalSpaceStr); } private void initUI() { tvPM_process_number = findViewById(R.id.tvPM_process_number); tvPM_memory_info = findViewById(R.id.tvPM_memory_info); lv_process_manager = findViewById(R.id.lv_process_manager); btPM_all_select = findViewById(R.id.btPM_all_select); btPM_reverse_select = findViewById(R.id.btPM_reverse_select); btPM_setting = findViewById(R.id.btPM_setting); tv_des = findViewById(R.id.tv_des); btPM_all_select.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); btPM_all_select.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); btPM_setting.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); //给listview设置滚动监听事件,实现常驻悬浮框的效果 lv_process_manager.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //滚动过程中调用方法 //AbsListView中view就是listView对象 //firstVisibleItem第一个可见条目索引值 //visibleItemCount当前一个屏幕的可见条目数 //总共条目总数 if(customerProcessInfoList!=null && systemProcessInfoList!=null){ if(firstVisibleItem>=customerProcessInfoList.size()+1){ //滚动到了系统条目 tv_des.setText("系统进程("+systemProcessInfoList.size()+")"); }else{ //滚动到了用户应用条目 tv_des.setText("用户进程("+customerProcessInfoList.size()+")"); } } } }); } /** * 带不同类型条目的listview(纯文本类型的条目,图片+文字类型的条目) */ private class MyAdapter extends BaseAdapter { //获取适配器中条目类型的总数,此处修改为两种(纯文本,图片+文字) @Override public int getViewTypeCount() { return super.getViewTypeCount()+1; } //指定索引指向的条目类型,条目类型状态码指定(0(复用系统),1) @Override public int getItemViewType(int position) { if(position==0||position==customerProcessInfoList.size()+1){ //返回0,代表纯文字的状态码 return 0; }else { //返回1,代表图片+文字状态码 return 1; } } //给listview添加两个描述条目 @Override public int getCount() { return systemProcessInfoList.size()+customerProcessInfoList.size()+2; } @Override public ProcessInfoBean getItem(int position) { //因为加了两个描述条目后,条目的顺序发生了改变 if(position==0||position==customerProcessInfoList.size()+1){ return null; }else { if(position<customerProcessInfoList.size()+1){ return customerProcessInfoList.get(position-1); }else { return systemProcessInfoList.get(position-customerProcessInfoList.size()-2); } } } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { int type=getItemViewType(position); if(type==0){ //在position==0或position==customerAppInfoList.size()+1这两处展示纯文本条目 //采用优化后的listview ViewTitleHolder viewTitleHolder=null; if(convertView==null){ convertView=View.inflate(getApplicationContext(),R.layout.listview_app_manager_item_title,null); viewTitleHolder=new ViewTitleHolder(); viewTitleHolder.tvAM_title = convertView.findViewById(R.id.tvAM_title); convertView.setTag(viewTitleHolder); }else { viewTitleHolder= (ViewTitleHolder) convertView.getTag(); } if(position==0){ viewTitleHolder.tvAM_title.setText("用户进程("+customerProcessInfoList.size()+")"); }else { viewTitleHolder.tvAM_title.setText("系统进程("+systemProcessInfoList.size()+")"); } return convertView; }else { //展示图片+文字条目 //采用优化后的listview ViewHolder viewHolder=null; if(convertView==null){ convertView=View.inflate(getApplicationContext(),R.layout.listview_process_manager_item,null); viewHolder=new ViewHolder(); viewHolder.iv_app_icon = convertView.findViewById(R.id.iv_app_icon); viewHolder.tvLV_name = convertView.findViewById(R.id.tvLV_name); viewHolder.tvLV_memory_info= convertView.findViewById(R.id.tvLV_memory_info); viewHolder.cb_process_manager=convertView.findViewById(R.id.cb_process_manager); convertView.setTag(viewHolder); }else { viewHolder= (ViewHolder) convertView.getTag(); } viewHolder.iv_app_icon.setBackgroundDrawable(getItem(position).icon); viewHolder.tvLV_name.setText(getItem(position).name); String sizeStr = Formatter.formatFileSize(getApplicationContext(), getItem(position).memSize); viewHolder.tvLV_memory_info.setText(sizeStr); //如果包名为当前应用,则隐藏checkbox if(getItem(position).packageName.equals(getPackageName())){ viewHolder.cb_process_manager.setVisibility(View.GONE); }else { viewHolder.cb_process_manager.setVisibility(View.VISIBLE); } viewHolder.cb_process_manager.setChecked(getItem(position).isCheck); return convertView; } } private class ViewHolder { ImageView iv_app_icon; TextView tvLV_name; TextView tvLV_memory_info; CheckBox cb_process_manager; } private class ViewTitleHolder { TextView tvAM_title; } } }
4.效果图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)