源码地址:https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem
使用方式一:XML布局中直接使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><com.test.festec.cehuaitem.widget.SideslipContainerandroid:id="@+id/sideslip_container01"android:layout_width="match_parent"android:layout_height="70dp"app:option_width="65dp"><com.test.festec.cehuaitem.widget.SideslipContentandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:background="@color/d5"android:paddingTop="20dp"android:textAlignment="center"android:textSize="20sp"android:text="content"android:layout_width="match_parent"android:layout_height="match_parent" /></com.test.festec.cehuaitem.widget.SideslipContent><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/blue"android:tag="add"android:text="增加" /><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/orange"android:tag="edit"android:text="编辑" /><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/red"android:tag="delete"android:text="删除" /></com.test.festec.cehuaitem.widget.SideslipContainer></LinearLayout>
Activity中监听
class MainActivity : Activity() {private lateinit var binding: ActivityMainBindingprivate var options = mutableListOf("增加", "编辑", "删除")private var optionBg = mutableListOf(R.color.blue, R.color.orange, R.color.red)@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)binding.sideslipContainer01.addOnClickListener(object : SideslipContainer.SideslipContainerOnClick {override fun optionOnClick(optionTag: Any) {Toast.makeText(this@MainActivity,"optionTag:$optionTag", Toast.LENGTH_SHORT).show()binding.sideslipContainer01.sideslipRecover()}override fun contentOnClick() {Toast.makeText(this@MainActivity,"content", Toast.LENGTH_SHORT).show()binding.sideslipContainer01.sideslipRecover()}})}}
使用方式二:代码方式使用
先定义一个容器
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><LinearLayoutandroid:id="@+id/container"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" /></LinearLayout>
Activity中动态添加
class MainActivity : Activity() {private lateinit var binding: ActivityMainBindingprivate var options = mutableListOf("增加", "编辑", "删除")private var optionBg = mutableListOf(R.color.blue, R.color.orange, R.color.red)@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// 创建侧滑容器,配置基础参数val sideslip = SideslipContainer(this, DensityUtil.dp2px(this, 65f))val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,DensityUtil.dp2px(this, 70f))sideslip.layoutParams = layoutParams// 创建侧滑内容val content = SideslipContent(this).apply {background = resources.getDrawable(R.color.black,null)}// 加入侧滑容器中sideslip.addView(content)// 创建选项卡,并加入侧滑容器中options.forEachIndexed { index, str ->val option = SideslipOption(this,str)option.text = stroption.background = resources.getDrawable(optionBg[index], null)sideslip.addView(option)}// 点击监听sideslip.addOnClickListener(object : SideslipContainer.SideslipContainerListener {override fun optionOnClick(optionTag: Any) {Log.e("TAG","optionTag:$optionTag")}override fun contentOnClick() {Log.e("TAG","content")}})binding.container.addView(sideslip)}}
使用方式三:结合RecyclerView使用
重写LayoutManager
// 重写LayoutManager,动态让RecyclerView 禁止/恢复 Y轴滚动
open class CustomLinerLayoutManager(context: Context) : LinearLayoutManager(context) {private var isScrollEnabled = truefun getEnabled(): Boolean {return isScrollEnabled}fun setScrollEnabled(flag: Boolean) {isScrollEnabled = flag}override fun canScrollVertically(): Boolean {return isScrollEnabled && super.canScrollVertically();}}
重写RecyclerView
class MyRecyclerView : RecyclerView {constructor(context: Context) : super(context)constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)init {addOnScrollListener(object : RecyclerView.OnScrollListener() {/**** public static final int SCROLL_STATE_IDLE = 0; : RecyclerView 当前未滚动。** public static final int SCROLL_STATE_DRAGGING = 1; : RecyclerView 当前正在被外部输入(例如用户触摸输入)拖动。** public static final int SCROLL_STATE_SETTLING = 2; : RecyclerView 当前正在动画到最终位置,而不是在外部控制。*/override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {childrenRecover()}}})}// view初始化private var viewInit = false// 上一会触摸的子Viewvar originalChild: SideslipContainer? = null// 当前触摸的子Viewvar currentChild: SideslipContainer? = nullprivate var customLayoutManager: CustomLinerLayoutManager? = nullprivate var childMoveCallback = object : ChildOnTouchCallback {override fun currentChildMove() {childrenRecover()}override fun originalChild(originalSideslip: SideslipContainer?) {originalChild = originalSideslip}override fun currentChild(currentContainer: SideslipContainer?) {currentChild = currentContainer}override fun listStopYScroll() {// Log.e("TAG", "List停止滚动")if (customLayoutManager!!.getEnabled()) {customLayoutManager?.setScrollEnabled(false)}}override fun listRecoverYScroll() {// Log.e("TAG", "List恢复滚动")if (!(customLayoutManager!!.getEnabled())) {customLayoutManager?.setScrollEnabled(true)}}}// 子View恢复private fun childrenRecover() {children.forEach {(it as SideslipContainer).sideslipRecover()}}override fun onViewAdded(child: View?) {// Log.e("TAG","onViewAdded")val sideslipContainer = (child as SideslipContainer)sideslipContainer.addOnChildMoveCallback(childMoveCallback)}// 当复用item,彻底超出屏幕,不可见时执行override fun onViewRemoved(child: View?) {// Log.e("TAG","onViewRemoved")(child as SideslipContainer).sideslipStateRest()}override fun onWindowFocusChanged(hasWindowFocus: Boolean) {// Log.e("TAG","onWindowFocusChanged")super.onWindowFocusChanged(hasWindowFocus)if (!viewInit) {customLayoutManager = (layoutManager as CustomLinerLayoutManager)}viewInit = true}interface ChildOnTouchCallback {// 有子View侧滑了fun currentChildMove()// 上一个触摸的子Viewfun originalChild(originalSideslip: SideslipContainer?)// 当前触摸的子Viewfun currentChild(currentContainer: SideslipContainer?)// 列表停止Y轴滚动fun listStopYScroll()// 列表恢复Y轴滚动fun listRecoverYScroll()}}
RecyclerView适配器
class MyListAdapter(var context: Context,var data: MutableList<Info>
) : RecyclerView.Adapter<MyListAdapter.MyViewHolder>() {private var options = mutableListOf("增加", "编辑", "删除")private var optionBg =mutableListOf(R.color.blue, R.color.orange, R.color.red)@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val itemView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false)val sideslip = sideslipContainer(itemView)return MyViewHolder(sideslip)}@SuppressLint("UseCompatLoadingForDrawables", "ResourceAsColor")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onBindViewHolder(holder: MyViewHolder, position: Int) {val sideslip = holder.itemView as SideslipContainer// 根据不同权限,添加不同的选项卡val optionsView = mutableListOf<SideslipOption>()if (data[position].level == 0) {optionsView.clear()} else if (data[position].level == 1) {val option = SideslipOption(context, options[1])option.text = options[1]option.background = context.resources.getDrawable(optionBg[1], null)optionsView.add(option)} else {options.forEachIndexed { index, str ->val option = SideslipOption(context, str)option.text = stroption.background = context.resources.getDrawable(optionBg[index], null)optionsView.add(option)}}sideslip.addMultipleOption(optionsView)// 点击回调sideslip.addOnClickListener(object : SideslipContainer.SideslipContainerOnClick {override fun optionOnClick(optionTag: Any) {Toast.makeText(context,"${holder.adapterPosition} -- optionTag:$optionTag",Toast.LENGTH_SHORT).show()sideslip.sideslipRecover()}override fun contentOnClick() {Toast.makeText(context,"${holder.adapterPosition} - content",Toast.LENGTH_SHORT).show()sideslip.sideslipRecover()}})holder.idTv.text = data[position].id.toString()holder.titleTv.text = data[position].titleholder.describeTv.text = data[position].describe}override fun getItemCount(): Int {return data.size}@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)private fun sideslipContainer(itemView: View): SideslipContainer {// 创建侧滑容器,配置基础参数val sideslip = SideslipContainer(context)sideslip.setOptionWidth(DensityUtil.dp2px(context, 65f))val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,DensityUtil.dp2px(context, 70f))sideslip.layoutParams = layoutParams// 创建侧滑内容val content = SideslipContent(context)content.addView(itemView)// 加入侧滑容器中sideslip.addView(content)// 创建选项卡,并加入侧滑容器中// options.forEachIndexed { index, str ->// val option = SideslipOption(context, str)// option.text = str// option.background = context.resources.getDrawable(optionBg[index], null)// sideslip.addView(option)// }return sideslip}class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var idTv: TextViewvar titleTv: TextViewvar describeTv: TextViewinit {idTv = itemView.findViewById(R.id.id_tv)titleTv = itemView.findViewById(R.id.title_tv)describeTv = itemView.findViewById(R.id.describe_tv)}}
}
Activity中绑定数据
class ListActivity : Activity() {private lateinit var binding: ListLayoutBindingprivate val data: MutableList<Info> = mutableListOf(Info(0, "title", "content", 2),Info(1, "title", "content", 1),Info(2, "title", "content", 2),Info(3, "title", "content", 2),Info(4, "title", "content", 2),Info(5, "title", "content", 1),Info(6, "title", "content", 1),Info(7, "title", "content", 2),Info(8, "title", "content", 2),Info(9, "title", "content", 1),Info(10, "title", "content", 1),Info(11, "title", "content", 2),Info(12, "title", "content", 2),Info(13, "title", "content", 1),Info(14, "title", "content", 1),Info(15, "title", "content", 2),Info(16, "title", "content", 2),Info(17, "title", "content", 2),Info(18, "title", "content", 2),Info(19, "title", "content", 1),Info(20, "title", "content", 2),Info(21, "title", "content", 1),Info(22, "title", "content", 2),Info(23, "title", "content", 2),Info(24, "title", "content", 2),Info(25, "title", "content", 1),Info(26, "title", "content", 2),Info(27, "title", "content", 1),Info(28, "title", "content", 2),Info(29, "title", "content", 2),Info(30, "title", "content", 2),Info(31, "title", "content", 1),Info(32, "title", "content", 1),Info(33, "title", "content", 2),Info(34, "title", "content", 2),Info(35, "title", "content", 1),)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ListLayoutBinding.inflate(layoutInflater)setContentView(binding.root)val adapter = MyListAdapter(this, data)val linearLayoutManager = CustomLinerLayoutManager(this)binding.root.layoutManager = linearLayoutManagerbinding.root.adapter = adapter}}