手把手教你做开源项目MyMeiZi 二(使用RecyclerView+Glide打造瀑布流)

Glide

一个专注于平滑滚动的图片加载和缓存库,相信大家也不会陌生,话说我以前一直使用的是Fresco,这次也是为了学习使用了Glide,谁上谁下这个不好区分,但是Glide更轻量级,究竟选择哪个还要看各位自己了

Github上我们可以看到关于Glide的用法。

// For a simple view:
@Override public void onCreate(Bundle savedInstanceState) {
  ...
  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);

  Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}

// For a simple image list:
@Override public View getView(int position, View recycled, ViewGroup container) {
  final ImageView myImageView;
  if (recycled == null) {
    myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
  } else {
    myImageView = (ImageView) recycled;
  }

  String url = myUrls.get(position);

  Glide
    .with(myFragment)
    .load(url)
    .centerCrop()
    .placeholder(R.drawable.loading_spinner)
    .crossFade()
    .into(myImageView);

  return myImageView;
}

非常的简单,with里面可以传Activity,Fragment,Glide会自动根据你的生命周期来判断暂停和加载,load可以传
loadcenterCrop和fitCenter就和设置ImageView的scaleType一样,into就是你的ImageView控件了。

RecyclerView

更加灵活的ListView,拔插式的设计能轻而易举的完成许多效果(拖动排序,滑动删除),而且使用StaggeredGridLayoutManager可以轻松的完成瀑布流样式

我们今天的主题就是使用Glide+RecyclerView完成MyMeiZi中的老司机界面
老司机
关于从网上用RxJava和Retrofit拿数据我们上一章已经讲过了这一次我们直接开始完成UI吧.手把手教你做开源项目MyMeiZi 一( RxJava + Retrofit)


既然RecyclerView自带瀑布流我们就轻轻松松的完成吧!

  @Override
    protected ItemHolder onAdapterCreateViewHolder(ViewGroup viewGroup, int viewType) {
        DriverView driverView = new DriverView(mContext);
        ItemHolder itemHolder = new ItemHolder(driverView);
        return itemHolder;
    }

    @Override
    protected void onAdapterBindViewHolder(ItemHolder viewHolder, int position) {
        viewHolder.driverView.setData(mData.get(position));
    }

因为图片高度不一样所以才能完成瀑布流样式,那么我们该怎么判断Item适当的高度呢,因为Item的宽度是固定的,所以我们可以根据宽度得到适当的高度(这叫自问自答).

<android.support.v7.widget.CardView
        android:id="@+id/view_card_feed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:scrollbars="vertical"
        app:cardCornerRadius="5dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/view_img_feed"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:scaleType="centerCrop"
                />

        </RelativeLayout>

    </android.support.v7.widget.CardView>

用Glide override和asBitmap的方法得到一个宽度为Item宽度高度为原始尺寸的图片

   Glide.with(getContext()).load(data.getUrl()).asBitmap().fitCenter().override(mBinding.viewImgFeed.getWidth(), BitmapImageViewTarget.SIZE_ORIGINAL).into(new DriverViewTarget(mBinding.viewImgFeed));

在BitmapImageViewTarget中对Item进行宽高的调整

  private class DriverViewTarget extends BitmapImageViewTarget {

        public DriverViewTarget(ImageView view) {
            super(view);
        }

        @Override
        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                int viewWidth = mBinding.viewImgFeed.getWidth();
                float scale = resource.getWidth() / (viewWidth * 1.0f);
                int viewHeight = (int) (resource.getHeight() * scale);
                setCardViewLayoutParams(viewWidth, viewHeight);
            super.onResourceReady(resource, glideAnimation);
        }
    }

恩,完美,运行一下!
run
看上去是没啥问题,瀑布流的样子也都出来了,不过慢滑和快滑时明显有一个重新排列的过程,这是因为每次划出来时会从缓存或者网上重新填充,而这个填充快慢就不一定了,可能Item填充顺序和第一次加载完毕时不一样,高度的计算顺序也不一样,这也就导致了如图中的效果,几个Item会不断的变换位置~


果然什么事都没有那么简单啊,不过我们已经知道这是因为高度计算的问题,那么我们可以新建立一个SizeModel类,来存储我们第一次加载时计算的高度,以后判断这个SizeModel如果存在可以直接用width和Height而不用再根据Bitmap重新计算一次,这也是本章的核心内容!!!!

public class SizeModel {

    private String url;
    private int height;
    private int width;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public boolean isNull() {
        return height == 0 || width == 0;
    }

    public void setSize(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

使用方法,首先在获取到网络数据时,把图片的url传给SizeModel,然后传给Adapter

  @Override
        public void onNext(GankIoModel.ResultsEntity resultsEntity) {
            mData.add(resultsEntity);
            SizeModel sizeModel = new SizeModel();
            sizeModel.setUrl(resultsEntity.getUrl());
            mSizeData.add(sizeModel);
            feedAdapter.setSizeModel(mSizeData);
            feedAdapter.notifyAdapterItemInserted(mData.size());
        }

然后再由Adapter传给我们的控件

 @Override
    protected void onAdapterBindViewHolder(ItemHolder viewHolder, int position) {
        viewHolder.driverView.setData(mData.get(position), mSizeModel.get(position));
    }

最后我们在控件中做处理判断

 if (!mSizeModel.isNull()) {
            setCardViewLayoutParams(mSizeModel.getWidth(), mSizeModel.getHeight());
        }


 private void setCardViewLayoutParams(int width, int height) {
        ViewGroup.LayoutParams layoutParams = mBinding.viewImgFeed.getLayoutParams();
        layoutParams.width = width;
        layoutParams.height = height;
        mBinding.viewImgFeed.setLayoutParams(layoutParams);
    }


 @Override
        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
            if (mSizeModel.isNull()) {
                int viewWidth = mBinding.viewImgFeed.getWidth();
                float scale = resource.getWidth() / (viewWidth * 1.0f);
                int viewHeight = (int) (resource.getHeight() * scale);
                setCardViewLayoutParams(viewWidth, viewHeight);
                mSizeModel.setSize(viewWidth, viewHeight);
            }
            super.onResourceReady(resource, glideAnimation);
        }

再次运行~
run


ok,看起来效果还是不错的,本章内容就到此为止啦

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值