流水不争先,争的是滔滔不绝

Android手把手朋友圈实战教程(十二)控件篇【内容(上)】

即时通讯软件开发 云聊IM 898℃

内容页里面今天主要实现图文的内容,因为纯文字的话内容页是无需展示的,网页分享则是固定的,只有图文是变化的。

如果平时浏览朋友圈,我们不难发现图文混编时,图片的数量对控件的大小是有影响的。

下面直接上两张图,很容易就可以发现端倪:

图1

图2

图3

  1. 图一:当图片是单张的时候,我们可以发现图片的大小并非固定的,但可以肯定的是,对于但张图片是有宽高上限。
  2. 图二:无论是两列还是三列,其item宽度都是一样的,而且都是正方形
  3. 图三:图片为4张是,呈“田”字排版,而且遵循第二点的规则。

而解决方案目前如下:

  1. 1 – 单张图片可以针对解决,另外布局
  2. 2 – item可以直接给定宽高。
  3. 3 – 当图片为4张,动态设置列数为2,由于第二点的原因,宽度都是一致的。

本篇解决第一点

首先需要知道的是,我们服务器下发的图片是一个jsonArray,也就是一个数组,而且type都是11,也就是说这个图组可能是1张,也可能是9张,但他们的type都是11。

因此我们需要在本地转换一下,在用gson解析完后,需要判断图片数量,等于1的话,就直接设定为我们本地定下的type,然后针对使用布局。

首先定义一下我们的type,这次我们定义为9:

type

然后复制原有布局,直接在我们的content里面塞入一个ImageView,定义一下宽高和最大高度。

大概如图效果(宽高最大的情况):

然后建立我们的item,并返回我们的res

/**
 * Created by 大灯泡 on 2016/2/27.
 * 图文(单张)
 * type=9
 */
public class ItemWithImgSingle extends BaseItemDelegate {

    public ItemWithImgSingle(){}

    @Override
    protected void bindData(int position, @NonNull View v, @NonNull MomentsInfo data, int dynamicType) {

    }

    @Override
    public int getViewRes() {
        return R.layout.dynamic_item_with_img_single;
    }

    @Override
    public void onFindView(@NonNull View parent) {

    }
}

得益于我们之前的封装,添加一个布局基本不怎么费力(至少不用去adapter写holder和swithc viewtype),接着我们去adapter注册一下,我们的布局就可以投入使用了。

注册布局

接下来就是实现我们的逻辑。

首先去到我们的请求解析里面,手动判断一下是否单张图片(*本文集并没有写请求相关的代码实现文章):

@Override
public void parseResponse(BaseResponse response, JSONObject json, int start, boolean hasMore) throws JSONException {
    hostInfo= JSONUtil.toObject(json.optString("hostInfo"),HostInfo.class);
    List momentsInfos=JSONUtil.toList(json.optString("moments"),new TypeToken>(){}
            .getType());
    setStart(start);
    
    //手动判断
    if (momentsInfos != null) {
        for (int i = 0; i < momentsInfos.size(); i++) {
            MomentsInfo momentsInfo = momentsInfos.get(i);
            if (momentsInfo.dynamicInfo != null &&
                    momentsInfo.dynamicInfo.dynamicType == DynamicType.TYPE_WITH_IMG) {
                if (momentsInfo.content.imgurl != null && momentsInfo.content.imgurl.size() == 1) {
                    momentsInfo.dynamicInfo.dynamicType = DynamicType.TYPE_IMG_SINGLE;
                }
            }
        }
    }
    response.setData(momentsInfos);
}

每次解析完后,我们遍历一次数组,得到type,如果type是图文,则判断图组长度,如果是1,则手动修改类型。

也许有人会觉得每次遍历这效率太低,而且会不会阻塞,这里回答一下:

  1. 首先,这个数组的长度是跟我们请求时发送的count有关,比如我们发送8条,就只会请求8条,所以这里的耗时几乎可以忽略
  2. 其次,我们的解析是覆写volley的request,在request里面执行的(parseNetworkResponse),volley每个请求都会弄到队列,而这个是异步的,所以并不会阻塞UI线程。详情可以看这里

这两部做好后,我们开始动工我们的item:

首先在onFindView里面初始化一些参数:

@Override
public void onFindView(@NonNull View parent) {
    mImageView= (ImageView) parent.findViewById(R.id.img_single);
    if (maxWidth==0){
        maxWidth= UIHelper.getScreenPixWidth(context)-UIHelper.dipToPx(context,90f);
    }
    if (maxHeight==0){
        maxHeight=UIHelper.dipToPx(context,175f);
    }
}

这里我们主要初始化最大宽高

然后在onBindData里面实现我们的操作:

在开干之前,我们先想想可以如何实现自适应大小:

  1. 得到图片的宽高,与我们的最大宽高相比,然后动态设置imageview的LayoutParams,然后再载入图片
  2. 得到图片的宽高,与我们的最大宽高相比,然后缩放图片

大致这两个方案,一个操作view,一个操作图片。这里我们采用第二个方案,原因无他,第一个方案不断的设置LayoutParams就会导致requestLayout(),然后导致测量/layout/重绘,造成的,依然是视觉上的卡顿。于是我们采取方案二。

方案二我们可以通过Glide官方文档得知,我们实现如下方法:

Glide.with(yourApplicationContext))
    .load(youUrl)
    .asBitmap()
    .into(new SimpleTarget(myWidth, myHeight) {
        @Override
        public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
            // Do something with bitmap here.
        }
    };

可以拿到图片信息,在这里我们就可以判断图片宽高,然后通过Glide的override方法来得到图片了。(ps:在下不知道在Glide里面又调用Glide好不好,直觉不太好,但在下暂时木有想到一个更好的方法。。。希望有经验的大大们可以传授一下-V-)

代码如下:

@Override
protected void bindData(int position, @NonNull View v, @NonNull MomentsInfo data, int dynamicType) {
    final String imgUrl=data.content.imgurl.get(0);
    if (!TextUtils.isEmpty(imgUrl)){
        Glide.with(context).load(imgUrl).asBitmap().into(new SimpleTarget() {
            @Override
            public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
                if (resource.getWidth() >= maxWidth) {
                    width = maxWidth;
                }
                else {
                    width = resource.getWidth();
                }
                resource.recycle();
                Glide.with(context)
                     .load(imgUrl)
                     .dontAnimate()
                     .crossFade()
                     .override(width,
                             (int) (width * ratio))
                     .into(mImageView);

            }
        });
    }
}

ratio是我们的最大宽高比,我们通过这个来等比压缩图片,而不至于达到fitXY那样的不计较任何成本的压缩。(简言之,压扁了好么。。。。或者压瘦了好么。。。。)

最终效果图如下:

效果图

附:本文使用的三张图片地址:

http://d.hiphotos.baidu.com/zhidao/pic/item/faedab64034f78f06cadf7e97a310a55b3191c01.jpg

http://www.qqpk.cn/Article/UploadFiles/201201/20120108160105455.jpg

http://cdn.duitang.com/uploads/item/201409/27/20140927123303_kdKje.thumb.700_0.jpeg

版权声明:部分文章、图片等内容为用户发布或互联网整理而来,仅供学习参考。如有侵犯您的版权,请联系我们,将立刻删除。
点击这里给我发消息