note_28:RecyclerView分标题栏和内容栏的实现和Glide加载图片并将图片变成灰度图

24 篇文章 0 订阅

RecyclerView分标题栏和内容栏的实现和Glide加载图片并将图片变成灰度图


参考:
RecyclerView有标题栏的分类列表 自定义列数(不同行设置不同个子项item)
Android图片转换类 1. Bitmap去色,转换为黑白的灰度图, 2. Bitmap图片加圆角效果
Glide变换
Class BitmapTransformation



1. RecyclerView分标题栏和内容栏的实现

(1) RecyclerView.ViewHolder

因为要区分标题栏和内容栏,所以这两个item的布局是不一样的,不大可能使用同一个itemView。
然而从源代码里可以看到,一个ViewHolder只能绑定一个itemView,所以需要分成两个ViewHolder。
但是一个RecyclerView.Adapter里面只能跟一个AppAdapter.ViewHolder,所以要把这两个ViewHolder变成内部类写在一个ViewHolder里面。

public class ViewHolder extends RecyclerView.ViewHolder {
	private static final int TYPE_TITLE = 0;

	public TitleViewHolder titleViewHolder;
	public ContentViewHolder contentViewHolder;

	// 相当于初始化了另外两个VieHolder的其中一个 因为一次onBindViewHolder只能绑定一个
	public ViewHolder(View view, int type) {
	    // 一定要写 而且不能改参数列表 也不能删掉super(itemView)
		super(view);
		if (type == TYPE_TITLE) titleViewHolder = new TitleViewHolder(view);
		else contentViewHolder = new ContentViewHolder(view);
	}

	public class TitleViewHolder {
		// 标题的布局 外面一层LinearLayout加里面一个TextView
		@BindView(R.id.title)
		TextView title;

		public TitleViewHolder(View itemView) {
			ButterKnife.bind(this, itemView);
		}
	}

	public class ContentViewHolder {
		// 内容的布局 外面一层LinearLayout里面一个ImageView
		@BindView(R.id.image)
		ImageView image;

		public ContentViewHolder(View itemView) {
			ButterKnife.bind(this, itemView);
		}
	}
}

(2) onAttachedToRecyclerView

由于这个RecyclerView是使用GridLayoutManager来完成的,所以如果是遇到标题的话,那标题应该是占满了一整行。

RecyclerView的部分源码

/**
  * Called by RecyclerView when it starts observing this Adapter.
  * <p>
  * Keep in mind that same adapter may be observed by multiple RecyclerViews.
  *
  * @param recyclerView The RecyclerView instance which started observing this adapter.
  * @see #onDetachedFromRecyclerView(RecyclerView)
  */
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
}

所以需要重写onAttachedToRecyclerView

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
	GridLayoutManager manager = (GridLayoutManager) recyclerView.getLayoutManager();
	// 设置一个item占的空间
	manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
		@Override
		public int getSpanSize(int i) {
			// 如果不是标题 那就站一格
			// 如果是标题 那就占满正行
			if (!mListItems.get(i).isTitle()) return 1;
			else return NUM_COLUMNS;
		}
	});
}

(3) getItemViewType

因为创建ViewHolder的实例的时候需要判断是标题栏还是内容栏,在onCreateViewHolder的时候会用上。

RecyclerView的部分源码

/**
  * Return the view type of the item at <code>position</code> for the purposes
  * of view recycling.
  *
  * <p>The default implementation of this method returns 0, making the assumption of
  * a single view type for the adapter. Unlike ListView adapters, types need not
  * be contiguous. Consider using id resources to uniquely identify item view types.
  *
  * @param position position to query
  * @return integer value identifying the type of the view needed to represent the item at
  *                 <code>position</code>. Type codes need not be contiguous.
  */
public int getItemViewType(int position) {
	return 0;
}

重写getItemViewType

@Override 
public int getItemViewType(int position) {
	if (mListItems.get(position).isTitle()) return VIEW_TYPE_TITLE;
	else return VIEW_TYTPE_CONTENT;
}

(4) onCreateViewHolder

前面在getItemViewType的时候已经给ViewHolder分了类型。

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
	LayoutInflater inflater = LayoutInflater.from(parent.getContext());
	View view;
	ViewHolder viewHolder = null;
	switch (viewType) {
		case VIEW_TYPE_TITLE:
			view = inflater.inflate(R.layout.adapter_title, null);
			viewHolder = new ViewHolder(view, VIEW_TYPE_TITLE);
			break;

		case VIEW_TYTPE_CONTENT:
			view = inflater.inflate(R.layout.adapter_content);
			viewHolder = new ViewHolder(view, VIEW_TYTPE_CONTENT);
			break;

		default:
			break;		
	}
	return viewHolder;
}

(5) onBindViewHolder

创建完ViewHoder之后就要绑定每个ViewHolder里面的信息,例如TextView里面要写些什么字,ImageView里面要放张什么图,
要不要给每一个item加个点击事件或者自己写个别的回调。

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
	Item item = mListItems.get(position);
	if (item.isTitle()) {
		holder.titleViewHolder.title.setText(item.getTitle());
	} else {
		holder.contentViewHolder.image.setImageDrawable(item.getIcon());
		holder.contentViewHolder.image.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Toast.makeText(mContext, "you click this imageView", Toast.LENGTH_SHORT).show();
			}
		});
	}
}

2. Glide加载图片并将图片变成灰度图

用回上面onBindViewHolder的代码,不过这个时候的图片不是本地获取的,而是从网上下载的。

// 因为存储的时候是String类型的网址 所以必须转成Uri类型
Uri uri = Uri.parse(item.getUri());

// Glide有提供transform函数对获取的图片进行转换
// 如果直接从holder.contentViewHolder.image中获取图片的话 是null
Glide.with(mContext)
		.load(uri)
		.transform(new Adapter.ColorfulToGrey(mContext))
		.into(holder.contentViewHolder.image);

灰度图的算法,从网上找的

// 官方推荐是继承BitmapTransformation来写
public class ColorfulToGrey extends BitmapTransformation {
	private static final String ID = "com.example.demo.ColorfulToGrey";

	public ColorfulToGrey(Context context) {
		super(context);
	}

	@Override
	protected Bitmap transform(BitmapPool bitmapPool, Bitmap bitmap, int i0, int i1) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
		Canvas canvas = new Canvas(result);
		Paint paint = new Paint();
		ColorMatrix ColorMatrix = new ColorMatrix();
		colorMatrix.setSaturation(0);
		ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
		paint.setColorFilter(filter);
		canvas.drawBitmap(bitmap, 0, 0, paint);
		return result;
	}

	@Override
	public String getId() {
		return ID;
	}

	@Override
	public int hashCode() {
		return ID.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null) return false;
		return obj instanceof Adapter.ColorfulToGrey;
	}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值