美文网首页Android进阶Android自定义控件自定义view相关
一起撸个朋友圈吧(step5) - 控件篇【内容(上)】

一起撸个朋友圈吧(step5) - 控件篇【内容(上)】

作者: Razerdp | 来源:发表于2016-02-27 16:14 被阅读663次

    项目地址:https://github.com/razerdp/FriendCircle
    一起撸个朋友圈吧这是本文所处文集,所有更新都会在这个文集里面哦,欢迎关注

    上篇链接:http://www.jianshu.com/p/ff9788581fb0
    下篇链接:http://www.jianshu.com/p/3d0cc6882e1a


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

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

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


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

    而解决方案目前如下:
    1 - 单张图片可以针对解决,另外布局
    2 - item可以直接给定宽高。
    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<MomentsInfo> momentsInfos=JSONUtil.toList(json.optString("moments"),new TypeToken<ArrayList<MomentsInfo>>(){}
                    .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,则手动修改类型。

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

    • 首先,这个数组的长度是跟我们请求时发送的count有关,比如我们发送8条,就只会请求8条,所以这里的耗时几乎可以忽略
    • 其次,我们的解析是覆写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里面实现我们的操作:

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

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

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

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

    Glide.with(yourApplicationContext))
        .load(youUrl)
        .asBitmap()
        .into(new SimpleTarget<Bitmap>(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<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> 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

    相关文章

      网友评论

      本文标题:一起撸个朋友圈吧(step5) - 控件篇【内容(上)】

      本文链接:https://www.haomeiwen.com/subject/xlvwkttx.html