android---常驻悬浮框效果的实现

一.效果展示



我不会做动态图片,现在图书馆也没有网络(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>

布局效果:
android---常驻悬浮框效果的实现_第1张图片

这个layout文件比较简单,就是在FrameLayout帧布局这块要注意下,帧布局下的空间都是一层一层叠加的,所以显示的效果是在LIstView上层覆盖了一个Textview。

三.Activity中的业务逻辑

实现这种效果的重点是在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的展示文字,从实现效果上看,就好像实现了常驻悬浮框的效果。

四.后记

写的比较笼统,可能只有我自己看懂了。。 就简单的记录下吧

你可能感兴趣的:(android---常驻悬浮框效果的实现)