RecyclerView其实都已经用了一段时间了,但是说实话,我是真的不太熟悉,而且看到自己项目用的这个BRVAH框架后,就觉得很神奇,因为之前不是刚学了下动画基础嘛,然后就想到处去实践,后来大佬就说这个框架很好用的,于是我就开始研究起来了,但是归根前提,还是简单说下RecyclerView的基础使用吧,这样也可以让小白们也看得懂,先附上最简单的用法哈:
看了这个之后是不是觉得还是挺好实现,哦哦,还有代码!!附上啦:
MyRecyclerViewAdapte,而ViewHolder作为内部类也写在里面了
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.NonNull
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.example.concatadapter.MyRecyclerViewAdapter.MyViewHolder
import java.util.*
/**
* 1、继承RecyclerView.Adapter
* 2、绑定ViewHolder
* 3、实现Adapter的相关方法
*/
class MyRecyclerViewAdapter(private val mContext: Context, recyclerView: RecyclerView) : RecyclerView.Adapter() {
private var onItemClickListener: OnItemClickListener? = null
private val mRv: RecyclerView
private var dataSource: MutableList
private var addDataPosition = -1
fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) {
this.onItemClickListener = onItemClickListener
}
fun setDataSource(dataSource: MutableList) {
this.dataSource = dataSource
notifyDataSetChanged()
}
/**
* ViewHolder 绑定数据
* @param myViewHolder
* @param position
*/
override fun onBindViewHolder(@NonNull myViewHolder: MyViewHolder, position: Int) {
myViewHolder.mIv.setImageResource(getIcon(position))
myViewHolder.mTv.text = dataSource[position]
/**
* 只在瀑布流布局中使用随机高度
*/
if (mRv.layoutManager?.javaClass=== StaggeredGridLayoutManager::class.java) {
val params =
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, randomHeight)
myViewHolder.mTv.layoutParams = params
} else {
val params = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
myViewHolder.mTv.layoutParams = params
}
// 改变ItemView背景颜色
if (addDataPosition == position) {
myViewHolder.mItemView.setBackgroundColor(Color.RED)
} else {
myViewHolder.mItemView.setBackgroundColor(Color.parseColor("#A4D3EE"))
}
myViewHolder.mItemView.setOnClickListener { // 调用接口的回调方法
if (onItemClickListener != null) {
onItemClickListener!!.onItemClick(position)
}
}
}
/**
* 返回数据数量
* @return
*/
override fun getItemCount(): Int {
return dataSource.size
}
private fun getIcon(position: Int): Int {
when (position % 5) {
0 -> return R.mipmap.a
1 -> return R.mipmap.b
2 -> return R.mipmap.c
3 -> return R.mipmap.d
4 -> return R.mipmap.e
}
return 0
}
/**
* 返回不同的ItemView高度
* @return
*/
private val randomHeight: Int
get() = (Math.random() * 1000).toInt()
/**
* 添加一条数据
* @param position
*/
fun addData(position: Int) {
addDataPosition = position
dataSource.add(position, "插入的数据")
notifyItemInserted(position)
// 刷新ItemView
notifyItemRangeChanged(position, dataSource.size - position)
}
/**
* 删除一条数据
* @param position
*/
fun removeData(position: Int) {
addDataPosition = -1
dataSource.removeAt(position)
notifyItemRemoved(position)
// 刷新ItemView
notifyItemRangeChanged(position, dataSource.size - position)
}
inner class MyViewHolder(@NonNull itemView: View) :
RecyclerView.ViewHolder(itemView) {
var mItemView: View = itemView
var mIv: ImageView = itemView.findViewById(R.id.iv)
var mTv: TextView = itemView.findViewById(R.id.tv)
}
/**
* ItemView点击事件回调接口
*/
interface OnItemClickListener {
fun onItemClick(position: Int)
}
init {
dataSource = ArrayList()
mRv = recyclerView
}
/**
* 创建并且返回ViewHolder
* @param
* @param
* @return
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(
LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false)
)
}
}
逻辑执行部分:
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.*
import java.util.*
class MainActivity : AppCompatActivity() {
private var mRecyclerView: RecyclerView? = null
private var mAdapter: MyRecyclerViewAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mRecyclerView = findViewById(R.id.recycler_view)
// 线性布局
val linearLayoutManager = LinearLayoutManager(this)
// 横向排列ItemView
// linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
// 数据反向展示
// linearLayoutManager.setReverseLayout(true);
mRecyclerView?.layoutManager = linearLayoutManager
mAdapter = MyRecyclerViewAdapter(this, mRecyclerView!!)
mRecyclerView?.adapter = mAdapter
mRecyclerView?.itemAnimator = DefaultItemAnimator()
// itemView点击事件监听
mAdapter?.setOnItemClickListener(object : MyRecyclerViewAdapter.OnItemClickListener{
override fun onItemClick(position: Int) {
Toast.makeText(this@MainActivity, "第" + position + "数据被点击", Toast.LENGTH_SHORT).show()
}
})
}
/**
* 添加数据
* @param
*/
fun onAddDataClick(view: View) {
val data: MutableList = ArrayList()
for (i in 0..19) {
val s = "第" + i + "条数据"
data.add(s)
}
mAdapter?.setDataSource(data)
}
/**
* 切换布局
* @param
*/
fun onChangeLayoutClick(view: View) {
// 从线性布局 切换为 网格布局
when {
mRecyclerView?.layoutManager?.javaClass === LinearLayoutManager::class.java -> {
// 网格布局
val gridLayoutManager = GridLayoutManager(this, 2)
mRecyclerView?.layoutManager = gridLayoutManager
}
mRecyclerView?.layoutManager?.javaClass === GridLayoutManager::class.java -> {
// 瀑布流布局
val staggeredGridLayoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
mRecyclerView?.layoutManager = staggeredGridLayoutManager
}
else -> {
// 线性布局
val linearLayoutManager = LinearLayoutManager(this)
mRecyclerView?.layoutManager = linearLayoutManager
}
}
}
/**
* 插入一条数据
* @param
*/
fun onInsertDataClick(view: View) {
mAdapter?.addData(1)
}
/**
* 删除一条数据
* @param
*/
fun onRemoveDataClick(view: View) {
mAdapter?.removeData(1)
}
}
emmm,好了,基本的RecyclerView就实现了!!
然后重点来了,我主要还是要说下BRVAH第三方框架,真的很好用,良心推荐!!!
github地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper
官方地址:https://www.jianshu.com/p/b343fcff51b0
我用这个框架主要是为了实现过渡动画添加和adapter组合!!!
代码都是官方GitHub里面的,只是因为我是小白,所以才在这里注释下了,各位客将就看下吧:
AnimationAdapter
import android.text.TextPaint
import android.text.style.ClickableSpan
import android.view.View
import android.widget.TextView
import com.chad.baserecyclerviewadapterhelper.R
import com.chad.baserecyclerviewadapterhelper.data.DataServer
import com.chad.baserecyclerviewadapterhelper.entity.Status
import com.chad.baserecyclerviewadapterhelper.utils.ClickableMovementMethod
import com.chad.baserecyclerviewadapterhelper.utils.SpannableStringUtils
import com.chad.baserecyclerviewadapterhelper.utils.Tips
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
/**
* 文 件 名: AnimationAdapter
* 创 建 人: Allen
* 创建日期: 16/12/24 15:33
* 邮 箱: [email protected]
* 修改时间:
* 修改备注:
*/
class AnimationAdapter : BaseQuickAdapter(R.layout.layout_animation, DataServer.getSampleData(100)) {
override fun convert(helper: BaseViewHolder, item: Status?) {
when (helper.layoutPosition.rem(3)) {
0 -> helper.setImageResource(R.id.img, R.mipmap.animation_img1)
1 -> helper.setImageResource(R.id.img, R.mipmap.animation_img2)
2 -> helper.setImageResource(R.id.img, R.mipmap.animation_img3)
else -> {
}
}
helper.setText(R.id.tweetName, "Hoteis in Rio de Janeiro")
val msg = "\"He was one of Australia's most of distinguished artistes, renowned for his portraits\""
//SpannableStringUtils这个就是另一个的知识点了,append可以把固定的内容拼接上,如果是想更换msg的里面内容的特定内容的字体颜色之类的话就用
//SpannableStringUtils.append("landscapes and nedes").setClickSpan(clickableSpan).create()
val msg1="landscapes and nedes"
(helper.getView(R.id.tweetText) as TextView).text = SpannableStringUtils.getBuilder(msg).append(msg1).setClickSpan(clickableSpan).create()
(helper.getView(R.id.tweetText) as TextView).movementMethod = ClickableMovementMethod.getInstance()
//设置焦点
(helper.getView(R.id.tweetText) as TextView).isFocusable = false
//设置是否可点击
(helper.getView(R.id.tweetText) as TextView).isClickable = false
//设置是否可长按
(helper.getView(R.id.tweetText) as TextView).isLongClickable = false
}
//设置点击时间
private val clickableSpan: ClickableSpan = object : ClickableSpan() {
override fun onClick(widget: View) {
Tips.show("事件触发了 landscapes and nedes")
}
override fun updateDrawState(ds: TextPaint) {
ds.color = context.resources.getColor(R.color.clickspan_color)
//增加下划线,因为默认是没有下划线的
ds.isUnderlineText = true
}
}
}
AnimationUseActivity
import android.os.Bundle
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.chad.baserecyclerviewadapterhelper.R
import com.chad.baserecyclerviewadapterhelper.adapter.AnimationAdapter
import com.chad.baserecyclerviewadapterhelper.animator.CustomAnimation1
import com.chad.baserecyclerviewadapterhelper.animator.CustomAnimation2
import com.chad.baserecyclerviewadapterhelper.entity.Status
import com.chad.baserecyclerviewadapterhelper.utils.Tips
import com.chad.library.adapter.base.BaseQuickAdapter
import com.jaredrummler.materialspinner.MaterialSpinner
import com.kyleduo.switchbutton.SwitchButton
/**
* https://github.com/CymChad/BaseRecyclerViewAdapterHelper
*
*
* modify by AllenCoder
*/
class AnimationUseActivity : AppCompatActivity() {
private lateinit var mRecyclerView: RecyclerView
private var mAnimationAdapter: AnimationAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_adapter_use)
mRecyclerView = findViewById(R.id.rv_list)
//setHasFixedSize 的作用就是确保尺寸是通过用户输入从而确保RecyclerView的尺寸是一个常数。RecyclerView 的Item宽或者高不会变。每一个Item添加或者删除都不会变。
// 如果你没有设置setHasFixedSized没有设置的代价将会是非常昂贵的
mRecyclerView.setHasFixedSize(true)
mRecyclerView.layoutManager = LinearLayoutManager(this)
initAdapter()
initMenu()
initView()
}
private fun initView() {
val mImgBtn = findViewById(R.id.img_back)
mImgBtn.setOnClickListener { finish() }
}
private fun initAdapter() {
mAnimationAdapter = AnimationAdapter()
//设置是否有动画效果
mAnimationAdapter!!.animationEnable = true
//Item中子项点击事件注册
mAnimationAdapter!!.addChildClickViewIds(R.id.img, R.id.tweetName, R.id.tweetText)
mAnimationAdapter!!.setOnItemChildClickListener { adapter, view, position ->
var content: String? = null
val status = adapter.getItem(position) as Status
when (view.id) {
R.id.img -> content = "img:" + status.userAvatar
R.id.tweetName -> content = "name:" + status.userName
R.id.tweetText -> content = "tweetText:" + status.userName
else -> {
}
}
//封装了Toast
Tips.show(content)
}
mRecyclerView.adapter = mAnimationAdapter
}
private fun initMenu() {
val spinner = findViewById(R.id.spinner)
spinner.setItems("AlphaIn", "ScaleIn", "SlideInBottom", "SlideInLeft", "SlideInRight", "Custom1", "Custom2")
spinner.setOnItemSelectedListener { _, position, _, _ ->
when (position) {
//透明度渐变,淡出淡入
0 -> mAnimationAdapter!!.setAnimationWithDefault(BaseQuickAdapter.AnimationType.AlphaIn)
//收缩效果
1 -> mAnimationAdapter!!.setAnimationWithDefault(BaseQuickAdapter.AnimationType.ScaleIn)
//底部弹出效果
2 -> mAnimationAdapter!!.setAnimationWithDefault(BaseQuickAdapter.AnimationType.SlideInBottom)
//左边弹出效果
3 -> mAnimationAdapter!!.setAnimationWithDefault(BaseQuickAdapter.AnimationType.SlideInLeft)
//右边弹出效果
4 -> mAnimationAdapter!!.setAnimationWithDefault(BaseQuickAdapter.AnimationType.SlideInRight)
//从顶层撞入安定的效果
5 -> mAnimationAdapter!!.adapterAnimation = CustomAnimation1()
//从左往右撞入安定的效果
6 -> mAnimationAdapter!!.adapterAnimation = CustomAnimation2()
else -> {
}
}
mRecyclerView.adapter = mAnimationAdapter
}
//init firstOnly state
//设置动画效果false为不限制,true为只显示一次
mAnimationAdapter!!.isAnimationFirstOnly = false
val switchButton = findViewById(R.id.switch_button)
switchButton.setOnCheckedChangeListener { _, isChecked ->
mAnimationAdapter!!.isAnimationFirstOnly = isChecked
mAnimationAdapter!!.notifyDataSetChanged()
}
}
}
好啦!!其实官方里面说得真好清楚了,大家就继续研究吧!!!