我不会做动态图片,现在图书馆也没有网络(PS:图书馆的100M网线接口一直都可以用的,但那时不知道为什么从昨天开始用不了了,于是只有手机放热点了。。心痛~),所以就截取三张图片,将就着看看。
注意顶部灰色的条目框,在上划的过程中的变化
这种效果在手机QQ联系人列表也可以见到。记录下来,避免以后忘记
下面就以我最近做的项目的软件管理功能作为例子,简单记录一下实现方法(只分析常驻悬浮框,其余展示逻辑不做分析)
<?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">
<TextView style="@style/TitleStyle" android:text="软件管理" />
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="5dp">
<TextView android:id="@+id/tv_memory" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="磁盘可用" />
<TextView android:id="@+id/tv_sd_memory" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="SD卡可用" />
</RelativeLayout>
<FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<ListView android:id="@+id/lv_app_list" android:layout_width="match_parent" android:layout_height="wrap_content">
</ListView>
<TextView android:id="@+id/tv_des" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ccc" android:textColor="#fff" android:textSize="16sp" />
</FrameLayout>
</LinearLayout>
这个layout文件比较简单,就是在FrameLayout帧布局这块要注意下,帧布局下的空间都是一层一层叠加的,所以显示的效果是在LIstView上层覆盖了一个Textview。
实现这种效果的重点是在Adapter中,代码贴出来如下:
class MyAdapter extends BaseAdapter {
//获取数据适配器中条目类型的总数,修改成两种(纯文本,图片+文字)
@Override
public int getViewTypeCount() {
return super.getViewTypeCount() + 1;
}
//指定索引指向的条目类型,条目类型状态码指定(0(复用系统),1)
@Override
public int getItemViewType(int position) {
if (position == 0 || position == mCustomerList.size() + 1) {
//返回0,代表纯文本条目的状态码
return 0;
} else {
//返回1,代表图片+文本条目状态码
return 1;
}
}
//listView中添加两个描述条目 (纯文本)
@Override
public int getCount() {
return mCustomerList.size()+1 + mSystemList.size()+1;
}
@Override
public AppInfo getItem(int position) {
if (position == 0 || position == mCustomerList.size() + 1) {
return null;
} else {
if (position < mCustomerList.size() + 1) {
return mCustomerList.get(position - 1);
} else {
//返回系统应用对应条目的对象
return mSystemList.get(position - mCustomerList.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) {
//展示灰色纯文本条目
ViewTitleHolder holder = null;
if (convertView == null) {
convertView = View.inflate(getApplicationContext(), R.layout.listview_app_item_title, null);
holder = new ViewTitleHolder();
holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
convertView.setTag(holder);
} else {
holder = (ViewTitleHolder) convertView.getTag();
}
if (position == 0) {
holder.tv_title.setText("用户应用(" + mCustomerList.size() + ")");
} else {
holder.tv_title.setText("系统应用(" + mSystemList.size() + ")");
}
return convertView;
} else {
//展示图片+文字条目
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(getApplicationContext(), R.layout.listview_app_item, null);
holder = new ViewHolder();
holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);
holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
holder.tv_path = (TextView) convertView.findViewById(R.id.tv_path);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.iv_icon.setBackgroundDrawable(getItem(position).getIcon());
holder.tv_name.setText(getItem(position).getName());
if (getItem(position).isSdCard()) {
holder.tv_path.setText("sd卡应用");
} else {
holder.tv_path.setText("手机应用");
}
return convertView;
}
}
}
两个ViewHolder用于优化listView
private static class ViewHolder {
ImageView iv_icon;
TextView tv_name;
TextView tv_path;
}
private static class ViewTitleHolder {
TextView tv_title;
}
重写了BaseAdapter的两个方法,如下:在一般做展示ListView中是不会用到的,但是在常驻悬浮框的效果中,这两个方法发是很关键的!
//获取数据适配器中条目类型的总数,修改成两种(纯文本,图片+文字)
@Override
public int getViewTypeCount() {
return super.getViewTypeCount() + 1;
}
//指定索引指向的条目类型,条目类型状态码指定(0(复用系统),1)
@Override
public int getItemViewType(int position) {
if (position == 0 || position == mCustomerList.size() + 1) {
//返回0,代表纯文本条目的状态码
return 0;
} else {
//返回1,代表图片+文本条目状态码
return 1;
}
}
super.getViewTypeCount()默认返回值为1,所以需要+1,View的类型有2种。getItemViewType(int position) 此方法根据条目的位置,给他们分别添加上索引值,纯文本的返回0,图片加文本,返回1;两种VIew如下:
纯文本的View R.layout.listview_app_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="match_parent" android:orientation="vertical">
<TextView android:id="@+id/tv_title" android:textSize="16sp" android:textColor="#fff" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ccc" />
</LinearLayout>
图片加文本的View R.layout.listview_app_item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView android:id="@+id/iv_icon" android:background="@mipmap/ic_launcher" android:layout_width="45dp" android:layout_height="45dp" />
<TextView android:id="@+id/tv_name" android:text="应用名称" android:textSize="18dp" android:layout_toRightOf="@+id/iv_icon" android:layout_width="wrap_content" android:textColor="#000" android:layout_height="wrap_content" />
<TextView android:id="@+id/tv_path" android:textSize="18dp" android:layout_toRightOf="@+id/iv_icon" android:text="应用安装路径" android:textColor="#000" android:layout_below="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" />
</RelativeLayout>
说到这里应该就知道了。常驻悬浮框也是作为ListView的一个条目展示出来的,只是要在Adapter中设置两种条目的布局
在ListView的滚动过程中修改中,帧布局里的TextView的展示
private void initList() {
lv_app_list = (ListView) findViewById(R.id.lv_app_list);
tv_des = (TextView) findViewById(R.id.tv_des);
lv_app_list.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当前一个屏幕的可见条目数
//totalItemCount总共条目总数
if (mCustomerList != null && mSystemList != null) {
if (firstVisibleItem >= mCustomerList.size() + 1) {
//滚动到了系统条目
tv_des.setText("系统应用(" + mSystemList.size() + ")");
} else {
//滚动到了用户应用条目
tv_des.setText("用户应用(" + mCustomerList.size() + ")");
}
}
}
});
到这个部分,就可以知道了,所谓的常驻悬浮框只是一个“障眼法”,在滚动的过程中去改变帧布局中最上层的TextView的展示文字,从实现效果上看,就好像实现了常驻悬浮框的效果。
写的比较笼统,可能只有我自己看懂了。。 就简单的记录下吧