文档章节

Android界面中包含ListView的屏幕截图问题记录

叶大侠
 叶大侠
发布于 2014/10/13 22:25
字数 1616
阅读 90
收藏 0

界面的布局情况:

<?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:background="@color/app_bg"
    android:orientation="vertical" >

    <include
        android:id="@+id/title_bar"
        layout="@layout/include_title_bar_no_back_btn" />

    <include
        android:id="@+id/loading_view"
        layout="@layout/layout_loading" />

    <ViewStub
        android:id="@+id/reload_viewstub"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:inflatedId="@+id/reload_view"
        android:layout="@layout/layout_reload" />

    <LinearLayout
        android:id="@+id/main_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <com.gushiyingxiong.app.views.listview.PullLoadMoreListView
            android:id="@+id/pull_refresh_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/main_tab_height"
            android:splitMotionEvents="false" />
    </LinearLayout>

</LinearLayout>

功能要求:实现全屏幕的截图功能,包括ListView中滑动出现的内容。

实现思路:由于ListView容器为了能加载大数量的Item,内部已经实现了对不可视资源的回收机制(详细可以参考: How ListView's recycling mechanism works),如果直接调用getChild的方式,会导致不可见的部分无法获取;因此,只能通过ListAdapter的getView来获取,然后调用每个item view的绘制过程,生成相关的图片,然后再拼起来,大概实现思路就是这样。

这里首先要解决的一个问题是:如何把View转化成图片?

我在这里参考了这篇文章:Android中View转换为Bitmap及getDrawingCache=null的解决方法

我使用了第二种方案有效,其思路也就是View的绘制流程 measure -> layout -> draw。

ListView 的Item布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/stock_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FF000000"
    android:minHeight="80dp"
    android:orientation="horizontal"
    android:padding="10dp" >

    <ImageView
        android:id="@+id/stock_item_logo_iv"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center"
        android:layout_marginRight="10dp"
        android:padding="1dp"
        android:scaleType="fitCenter"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="right|center_vertical"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/stock_item_earn_percent_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:text="@string/hello_world"
            android:textColor="#FFFFFFFF"
            android:textSize="14sp"
            android:textStyle="bold" />
    </LinearLayout>

</LinearLayout>

我们想要的是:

但是可能会变成:

原因大概是由于调用getView返回的View一般都是通过View.inflate得到的,因此在measure的过程中没有上一层父容器的尺寸参考,所以在传入measure参数为:

view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

的时候,就会只能刚好装下里面的View,因此看起来变短了。

我们可以这样子修改,指定View的宽度或者高度,在这里,我需要指定它的宽度(width是屏幕宽度):

view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

好了,ListView的截图代码看起来大概就像这样子:

public  static Bitmap  createBitmap(ListView listView){
    int titleHeight,width, height, rootHeight=0;
    Bitmap bitmap;
    Canvas canvas;
    int yPos;
    int listItemNum;
    List<View> childViews = null;
        
    width = getScreenWidth();//宽度等于屏幕宽    

    ListAdapter listAdapter = listView.getAdapter();
    listItemNum = listAdapter.getCount()>
    childViews = new ArrayList<View>(listItemNum);
    View itemView;
    //计算整体高度:
    for(int pos=0; pos < listItemNum; ++pos){
        itemView = listAdapter.getView(pos, null, rootView);
        //measure过程
        itemView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        childViews.add(itemView);
        rootHeight += itemView.getMeasuredHeight();
    }

    height = rootHeight;
    bitmap = BitmapUtil.createBitmap(width, height, Config.ARGB_8888);
    canvas = new Canvas(bitmap);

    Bitmap itemBitmap;
    View itemView;
    int childHeight;
    //把每个ItemView生成图片,并画到背景画布上
    for(int pos=0; pos < childViews.size(); ++pos){
        itemView = childViews.get(pos);
        childHeight = itemView.getMeasuredHeight();
        itemBitmap = viewToBitmap(itemView,width,childHeight);
        if(itemBitmap!=null){
            canvas.drawBitmap(itemBitmap, 0, yPos, null);
        }
        yPos = childHeight +yPos;
    }
    
    canvas.save(Canvas.ALL_SAVE_FLAG);
    canvas.restore();
    return bitmap;
}

private static Bitmap viewToBitmap(View view,int viewWidth, int viewHeight){
        view.layout(0, 0, viewWidth, viewHeight);
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
}

到这里就完了么?可能还没有。。。笔者就碰到了这种情况:Item的部分内容没有画出来...

正确:

错误:

既然有的出来了,有的没出来,羊毛肯定就出在羊身上了...

具体原因我也暂时没有分析,把代码贴出来给大家做参考吧:

正确布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/stock_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/list_item_selector"
    android:minHeight="80dp"
    android:padding="@dimen/app_padding" >

    <ImageView
        android:id="@+id/stock_item_logo_iv"
        android:layout_width="@dimen/logo_img_width"
        android:layout_height="@dimen/logo_img_height"
        android:layout_gravity="center"
        android:layout_marginRight="10dp"
        android:padding="1dp"
        android:scaleType="fitCenter" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:minWidth="130dip"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/stock_item_name_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="@color/text_white"
            android:textSize="@dimen/font_48" />

        <TextView
            android:id="@+id/stock_item_code_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="@color/text_gray"
            android:textSize="@dimen/text_size_11" />

        <TextView
            android:id="@+id/stock_item_text_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:singleLine="true"
            android:textColor="@color/text_gray"
            android:textSize="@dimen/text_size_11" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical|right"
        android:orientation="vertical" >

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@+id/stock_item_oder_price"
                android:layout_centerVertical="true"
                android:layout_marginRight="2dp"
                android:layout_marginTop="2dip"
                android:singleLine="true"
                android:text="委托:"
                android:textColor="@color/text_gray"
                android:textSize="@dimen/text_size_10" />

            <TextView
                android:id="@+id/stock_item_oder_price"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:minWidth="@dimen/stock_list_item_oder_price_width"
                android:gravity="right"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginTop="2dip"
                android:textColor="@color/stock_high_red"
                android:textSize="@dimen/text_size_9"
                android:textStyle="bold" />
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@+id/stock_item_trade"
                android:layout_centerVertical="true"
                android:layout_marginRight="2dp"
                android:layout_marginTop="2dip"
                android:singleLine="true"
                android:text="实时:"
                android:textColor="@color/text_gray"
                android:textSize="@dimen/text_size_10" />

            <TextView
                android:id="@+id/stock_item_trade"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:minWidth="@dimen/stock_list_item_oder_price_width"
                android:gravity="right"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginTop="2dip"
                android:textColor="@color/text_white"
                android:textSize="@dimen/text_size_9"
                android:textStyle="bold" />
        </RelativeLayout>
    </LinearLayout>

</LinearLayout>

失败的布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/stock_item"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/list_item_selector"
    android:minHeight="80dp"
    android:orientation="horizontal"
    android:padding="@dimen/app_padding" >

    <ImageView
        android:id="@+id/stock_item_logo_iv"
        android:layout_width="@dimen/logo_img_width"
        android:layout_height="@dimen/logo_img_height"
        android:layout_gravity="center"
        android:layout_marginRight="10dp"
        android:padding="1dp"
        android:scaleType="fitCenter" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:gravity="center"
        android:minWidth="130dip"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/stock_item_name_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="@color/text_white"
            android:textSize="@dimen/font_48" />

        <TextView
            android:id="@+id/stock_item_code_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textColor="@color/text_gray"
            android:textSize="@dimen/text_size_11" />

        <TextView
            android:id="@+id/stock_item_text_tv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:singleLine="true"
            android:textColor="@color/text_gray"
            android:textSize="@dimen/text_size_11" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="right|center_vertical"
        android:minWidth="@dimen/stock_list_item_price_width"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical|right" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginRight="2dp"
                android:layout_marginTop="2dip"
                android:gravity="center_vertical|right"
                android:singleLine="true"
                android:text="委托:"
                android:textColor="@color/text_gray"
                android:textSize="@dimen/text_size_10"
                 />

            <TextView
                android:id="@+id/stock_item_oder_price"
                  android:layout_width="wrap_content"
                android:minWidth="@dimen/stock_list_item_oder_price_width"
                android:maxWidth="@dimen/stock_list_item_oder_price_width"
                android:layout_height="match_parent"
                android:layout_marginTop="2dip"
                android:gravity="center_vertical|right"
                android:singleLine="true"
                android:textColor="@color/stock_high_red"
                android:textSize="@dimen/text_size_9"
                android:textStyle="bold" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical|right" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginRight="2dp"
                android:layout_marginTop="2dip"
                android:gravity="center_vertical|right"
                android:singleLine="true"
                android:textColor="@color/text_gray"
                android:text="实时:"
                android:textSize="@dimen/text_size_10"
                  />

            <TextView
                android:id="@+id/stock_item_trade"
                android:layout_width="wrap_content"
                android:minWidth="@dimen/stock_list_item_oder_price_width"
                android:maxWidth="@dimen/stock_list_item_oder_price_width"
                android:layout_height="match_parent"
                android:layout_marginTop="2dip"
                android:gravity="center_vertical|right"
                android:singleLine="true"
                android:textColor="@color/text_white"
                android:textSize="@dimen/text_size_9"
                android:textStyle="bold" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

最后分享一张成功截图全貌:

原文:http://www.darcye.com/article/84263064

© 著作权归作者所有

共有 人打赏支持
叶大侠

叶大侠

粉丝 57
博文 44
码字总数 67312
作品 5
广州
程序员
ListView 空值时的友好提示

做 项目的时候,如果ListView或者gridView为空,进入界面一大片的空白,不是很好看,这个时候我们希望没有数据的时候给出提示,完全可以通过 手动判断,当ListView中的size为0,显示或者隐藏...

jxlgzwh
2013/07/19
0
0
自定义Android的ListView布局和各Item的背景色

Android中的ListView是用得非常频繁的一种组件,同时ListView也是一种很强大的组件,你可以为每一行自定义布局,也可以修改各行的 背景色。自定义布局比较容易,自己实现一个layout的布局文件...

LiSteven
2013/03/28
0
0
如何在触摸模式(Touch Mode)下高亮显示ListView选中行

这应该是大部分Android开发者在使用ListView时会碰到问题,在解决这个问题前,需要先了解什么叫触摸模式。 触摸模式(Touch Mode),在Android SDK的官方文档中有详细解释(http://developer.a...

Dean83
2012/06/19
0
0
Android listview

一:Android 弹软键盘时listview的变化控制: 问题描述:界面中有三部分,上面是标题栏,中间是Listview,下面是输入框。当点击输入框时,保持标题栏,挤压ListView。最终效果类似于微信聊天界...

当空皓月
2015/01/16
0
0
Android手机平板两不误,使用Fragment实现兼容手机和平板的程序

记得我之前参与开发过一个华为的项目,要求程序可以支持好几种终端设备,其中就包括Android手机和Android Pad。然后为了节省人力,公司无节操地让Android手机和Android Pad都由我们团队开发。...

带梦想一7飞
2013/06/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring加载properties文件的两种方式

在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取properties里面的配置,这样后期只需要改动properties文件即可,不需要修...

架构师springboot
36分钟前
0
0
分布式事务,原来可以这么玩?

多个数据要同时操作,如何保证数据的完整性,以及一致性? 答 : 事务 ,是常见的做法。 举个栗子: 用户下了一个订单,需要修改 余额表 , 订单 表 , 流水 表 ,于是会有类似的伪代码: st...

微笑向暖wx
38分钟前
2
0
IE6兼容PNG32图片显示PNG8图片

IE6并不是不支持PNG图片,只是不支持半透明通道。 是支持PNG8色表引索全透明的。 以往都是通过滤镜或统统使用PNG8实现兼容。 但是我发现twitter的png图标可以在chrome中显示png32,在IE6显示...

linsk1998
50分钟前
0
0
linux运维需要掌握的基础知识

踏入linux运维工程师这一职业,其实有很多工具技能需要掌握,下面我来给大家一一介绍。 1、shell脚本和另一个脚本语言,shell是运维人员必须具备的,不懂这个连入职都不行,至少也要写出一些...

linuxprobe16
51分钟前
0
0
《netty入门与实战》笔记-03:数据传输载体 ByteBuf 介绍

ByteBuf结构 首先,我们先来了解一下 ByteBuf 的结构 以上就是一个 ByteBuf 的结构图,从上面这幅图可以看到: ByteBuf 是一个字节容器,容器里面的的数据分为三个部分,第一个部分是已经丢弃...

Funcy1122
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部