日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Kotlin binding+RecyclerView实现支付宝首页更多、应用编辑界面

發布時間:2023/12/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Kotlin binding+RecyclerView实现支付宝首页更多、应用编辑界面 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

activity 主布局頁面:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/bg_white"android:orientation="vertical"><RelativeLayoutandroid:id="@+id/title"android:layout_width="fill_parent"android:layout_height="48dp"android:background="@color/colorBase" ><TextViewandroid:layout_height="wrap_content"android:layout_width="wrap_content"android:text="@string/app_title"android:layout_marginLeft="20dp"android:layout_gravity="center_vertical"android:layout_centerInParent="true"android:layout_alignParentLeft="true"android:textSize="12sp"/><TextViewandroid:id="@+id/submit"android:textSize="20sp"android:textColor="@color/colorWhite"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="5dp"android:layout_alignParentRight="true"android:layout_centerInParent="true"android:gravity="center_vertical"android:text="保存"/></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:padding="10dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我的應用"android:textColor="#333333"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:text="(按住可拖動調整順序)"android:textColor="#808080"android:textSize="13sp" /></LinearLayout><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerViewExist"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingRight="10dp" /><Viewandroid:layout_width="match_parent"android:layout_height="4dp"android:background="@color/line_color"></View><HorizontalScrollViewandroid:id="@+id/horizonLScrollView"android:layout_width="match_parent"android:layout_height="35dp"android:scrollbarThumbHorizontal="@color/transparent"android:scrollbars="none"><RadioGroupandroid:id="@+id/rg_tab"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center_vertical"android:orientation="horizontal" /></HorizontalScrollView><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="@color/line_color"></View><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerViewAll"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:paddingRight="10dp" /> </LinearLayout>

activity 代碼:

package com.daobo.wandimport android.annotation.SuppressLint import android.content.Context import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.View import kotlinx.android.synthetic.main.activity_main.* import android.view.View.OnClickListener import androidx.recyclerview.widget.GridLayoutManager import com.daobo.wand.ui.* import android.widget.RadioButton import android.util.TypedValue import android.view.Gravity import androidx.recyclerview.widget.RecyclerView import android.app.Activity import android.os.Build import android.util.DisplayMetrics import android.widget.Toast import android.widget.CompoundButton import androidx.annotation.RequiresApi import androidx.core.content.ContextCompat import com.daobo.wand.ui.adapter.FunctionAdapter import com.daobo.wand.ui.adapter.FunctionBlockAdapter import com.daobo.wand.ui.listener.DefaultItemCallback import com.daobo.wand.ui.listener.DefaultItemTouchHelper import com.daobo.wand.ui.util.SFUtils/*** 主菜單頁面* @author xiaolong.li* @time 2020-02-14*/ class MainActivity : AppCompatActivity(), OnClickListener {private var blockAdapter: FunctionBlockAdapter? = nullprivate var functionAdapter: FunctionAdapter? = nullprivate var gridManager: GridLayoutManager? = nullprivate var scrollTab = ArrayList<String>()private var itemWidth = 0private var lastRow = 0private var isMove = false//滑動狀態private var scrollPosition = 0private var currentTab: String? = null//當前的標簽private var tabWidth = 0//標簽寬度private var allData: ArrayList<FunctionItem>? = nullprivate var selData: ArrayList<FunctionItem>? = nullprivate var sfUtils: SFUtils? = nullprivate val maxCount = 14private var isDrag = falseoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)init()addListener()submit.setOnClickListener(this)}private fun init () {sfUtils = SFUtils(this)allData = sfUtils!!.getAllFunctionItems() //sfUtils!!.getAllFunctionWithState()selData = sfUtils!!.getSelectFunctionItem()blockAdapter = FunctionBlockAdapter(this, selData!!)recyclerViewExist.layoutManager = GridLayoutManager(this, 4)recyclerViewExist.adapter = blockAdapterrecyclerViewExist.addItemDecoration(SpaceItemDecoration(4, dip2px(this, 10.0F)))val callback = DefaultItemCallback(blockAdapter!!)val helper = DefaultItemTouchHelper(callback)helper.attachToRecyclerView(recyclerViewExist)gridManager = GridLayoutManager(this, 4)gridManager!!.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {override fun getSpanSize(position: Int): Int {val fi = allData!![position]return if (fi.isTitle) 4 else 1}}functionAdapter = FunctionAdapter(this, allData!!)recyclerViewAll.layoutManager = gridManagerrecyclerViewAll.adapter = functionAdapterval spaceDecoration = SpaceItemDecoration(4, dip2px(this, 10.0F))recyclerViewAll.addItemDecoration(spaceDecoration)itemWidth = getAtyWidth(this) / 4 + dip2px(this, 2.0F)resetEditHeight(selData!!.size)initTab()}private fun initTab () {try {val tabs = sfUtils!!.getTabFunctionItems()if (tabs != null && tabs.isNotEmpty()) {currentTab = tabs[0].mNameval padding = dip2px(this, 10.0F)val size = tabs.sizefor (i in 0 until size) {val item = tabs[i]if (item.isTitle) {scrollTab.add(item.mName.toString())val rb = RadioButton(this)rb.setPadding(padding, 0, padding, 0)rb.buttonDrawable = nullrb.gravity = Gravity.CENTERrb.text = item.mNamerb.tag = item.subItemCountrb.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14F)try {rb.setTextColor(ContextCompat.getColorStateList(this, R.color.colorGray))} catch (e: Exception) {e.printStackTrace()}rb.setCompoundDrawablesWithIntrinsicBounds(null, null, null,ContextCompat.getDrawable(this, R.drawable.bg_block_tab))rb.setOnCheckedChangeListener(onCheckedChangeListener)rg_tab.addView(rb)}}(rg_tab.getChildAt(0) as RadioButton).isChecked = true}} catch (e: Exception) {e.printStackTrace()}}private fun resetEditHeight(size: Int) {var size = sizetry {if (size == 0) {size = 1}var row = size / 4 + if (size % 4 > 0) 1 else 0if (row <= 0)row = 1if (lastRow != row) {lastRow = rowval params = recyclerViewExist.layoutParamsparams.height = itemWidth * rowrecyclerViewExist.layoutParams = params}} catch (e: Exception) {e.printStackTrace()}}private val onCheckedChangeListener =CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->try {val position = buttonView.tag as Intval text = buttonView.text.toString()if (currentTab != text && isChecked) {currentTab = textmoveToPosition(position)}} catch (e: Exception) {e.printStackTrace()}}private fun moveToPosition(position: Int) {val first = gridManager!!.findFirstVisibleItemPosition()val end = gridManager!!.findLastVisibleItemPosition()if (first == -1 || end == -1)returnif (position <= first) { //移動到前面gridManager!!.scrollToPosition(position)} else if (position >= end) { //移動到后面isMove = truescrollPosition = positiongridManager!!.smoothScrollToPosition(recyclerViewAll, null, position)} else {//中間部分val n = position - gridManager!!.findFirstVisibleItemPosition()if (n > 0 && n < allData!!.size) {val top = gridManager!!.findViewByPosition(position)!!.toprecyclerViewAll.scrollBy(0, top)}}}private val onScrollListener = object : RecyclerView.OnScrollListener() {override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {super.onScrollStateChanged(recyclerView, newState)try {if (isMove && newState == RecyclerView.SCROLL_STATE_IDLE) {isMove = falseval view = gridManager!!.findViewByPosition(scrollPosition)if (view != null) {val top = view.toprecyclerView.scrollBy(0, top)}}isDrag = newState == RecyclerView.SCROLL_STATE_DRAGGING} catch (e: Exception) {e.printStackTrace()}}override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {super.onScrolled(recyclerView, dx, dy)if (isDrag) { //拖動過程中val position = gridManager!!.findFirstVisibleItemPosition()if (position > 0) {for (i in 0 until position + 1) {if (allData!![i].isTitle) {currentTab = allData!![i].mName}}scrollTab(currentTab!!)}}}}private fun scrollTab(newTab: String) {try {val position = scrollTab.indexOf(currentTab)val targetPosition = scrollTab.indexOf(newTab)currentTab = newTabif (targetPosition != -1) {val x = (targetPosition - position) * getTabWidth()val radioButton = rg_tab.getChildAt(targetPosition) as RadioButtonradioButton.setOnCheckedChangeListener(null)radioButton.isChecked = trueradioButton.setOnCheckedChangeListener(onCheckedChangeListener)horizonLScrollView.scrollBy(x, 0)}} catch (e: Exception) {e.printStackTrace()}}private fun getTabWidth(): Int {if (tabWidth == 0) {if (rg_tab != null && rg_tab.childCount !== 0) {tabWidth = rg_tab.width / rg_tab.childCount}}return tabWidth}private fun dip2px(context: Context, dpValue: Float): Int {val scale = context.resources.displayMetrics.densityreturn (dpValue * scale + 0.5f).toInt()}private fun getAtyWidth(context: Context): Int {return try {val mDm = DisplayMetrics()(context as Activity).windowManager.defaultDisplay.getMetrics(mDm)mDm.widthPixels} catch (e: Exception) {0}}private fun addListener() {functionAdapter!!.setOnItemAddListener(object : FunctionAdapter.OnItemAddListener {override fun add(item: FunctionItem): Boolean {if (selData != null && selData!!.size < maxCount) { // 更新選擇列表,所有列表已在內部進行更新try {selData!!.add(item)resetEditHeight(selData!!.size)blockAdapter!!.notifyDataSetChanged()item.mIsSelect = truereturn true} catch (e: Exception) {e.printStackTrace()}return false} else {Toast.makeText(this@MainActivity, "選中的模塊不能超過" + maxCount + "個",Toast.LENGTH_SHORT).show()return false}}})blockAdapter!!.setOnItemRemoveListener(object : FunctionBlockAdapter.OnItemRemoveListener {override fun remove(item: FunctionItem) {// 更新所有列表,選擇列表已在內部進行更新try {if (item?.mName != null) {for (i in allData!!.indices) {val data = allData!![i]if (data?.mName != null) {if (item.mName.equals(data.mName)) {data.mIsSelect = falsebreak}}}functionAdapter!!.notifyDataSetChanged()}resetEditHeight(selData!!.size)} catch (e: Exception) {e.printStackTrace()}}})recyclerViewAll.addOnScrollListener(onScrollListener)}override fun onClick(v: View?) {//TODO("not implemented")// To change body of created functions use File | Settings | File Templates.var intent = Intent()when(v?.id) {R.id.submit ->{//點擊了sfUtils!!.saveSelectFunctionItem(selData!!)sfUtils!!.saveAllFunctionWithState(allData!!)Toast.makeText(this@MainActivity, "保存成功!",Toast.LENGTH_SHORT).show()}}}}

自定義控件代碼:SquareRelativeLayout

package com.daobo.wand.ui import android.content.Context import android.util.AttributeSet import android.view.View import android.widget.RelativeLayout class SquareRelativeLayout : RelativeLayout {constructor (context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)constructor (context: Context, attrs: AttributeSet) : super(context, attrs)constructor (context: Context) : super(context)override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {var widthMeasureSpec = widthMeasureSpecvar heightMeasureSpec = heightMeasureSpecsetMeasuredDimension(View.getDefaultSize(0, widthMeasureSpec),View.getDefaultSize(0, heightMeasureSpec))val childWidthSize = measuredWidthwidthMeasureSpec =View.MeasureSpec.makeMeasureSpec(childWidthSize, View.MeasureSpec.EXACTLY)heightMeasureSpec = widthMeasureSpecsuper.onMeasure(widthMeasureSpec, heightMeasureSpec)} } SpaceItemDecoration類: package com.daobo.wand.ui import androidx.recyclerview.widget.RecyclerView import android.graphics.Canvas import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView.ItemDecorationclass SpaceItemDecoration (row: Int, space: Int) : ItemDecoration() {private var mRow = rowprivate val mSpace = spaceoverride fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {outRect.left = mSpaceoutRect.bottom = mSpace//if (parent.getChildAdapterPosition(view) % row == 0)//outRect.left = 0}override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {super.onDrawOver(c, parent, state)}}

bean 類:

package com.daobo.wand.uiclass TabItem(tabName : String, functionItems : ArrayList<FunctionItem>) {private var mTtabName = tabNameprivate var mFunctionItems: ArrayList<FunctionItem>? = functionItemsfun getTabName(): String {return mTtabName}fun setTabName(tabName: String) {this.mTtabName = tabName}fun getFunctionItems(): ArrayList<FunctionItem>? {return mFunctionItems}fun setFunctionItems(functionItems: ArrayList<FunctionItem>) {this.mFunctionItems = functionItems} } package com.daobo.wand.uiclass FunctionItem {var mName: String? = nullvar mIsSelect = falsevar mImageUrl = ""var mBackground = ""var isTitle = falsevar subItemCount = 0constructor(name: String, isSelect: Boolean, imageUrl: String, background: String) {this.mName = namethis.mIsSelect = isSelectthis.mImageUrl = imageUrlthis.mBackground = background}constructor(name: String, isTitle: Boolean, subItemCount: Int) {this.mName = namethis.isTitle = isTitlethis.subItemCount = subItemCount}constructor(name: String, isTitle: Boolean) {this.mName = namethis.isTitle = isTitle} } package com.daobo.wand.ui.viewbeanclass FuncItemViewBean {var Name : String ? = ""var BtnImgSrc : Int = 0var IvImgSrc : Int = 0}

?item 布局xml: layout_function_text

<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variable name="name" type="String"/></data><TextViewandroid:id="@+id/func_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/bg_white"android:drawableLeft="@drawable/item_block_left"android:gravity="center_vertical"android:paddingBottom="4dp"android:paddingTop="4dp"android:textColor="@color/black"android:textSize="18sp"android:text="@{name}"/> </layout>

layout_function_item

<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variable name="funcItem" type="com.daobo.wand.ui.viewbean.FuncItemViewBean"/></data><com.daobo.wand.ui.SquareRelativeLayoutandroid:id="@+id/item"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/bg_grid_press"><LinearLayoutandroid:id="@+id/layout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:gravity="center"android:orientation="vertical"><ImageViewandroid:id="@+id/iv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@null"android:contentDescription="@string/app_name"android:scaleType="centerInside"android:src="@{funcItem.ivImgSrc}"/><TextViewandroid:id="@+id/text"android:layout_marginTop="2dp"android:lines="2"android:textSize="12sp"android:paddingLeft="5dp"android:paddingRight="5dp"android:gravity="center_horizontal"android:textColor="@color/black"android:layout_gravity="center_horizontal"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{funcItem.Name}"/></LinearLayout><ImageViewandroid:id="@+id/btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:layout_marginRight="1dp"android:layout_marginTop="1dp"android:background="@null"android:contentDescription="@string/app_name"android:padding="4dp"android:scaleType="centerInside"android:src="@{funcItem.btnImgSrc}" /></com.daobo.wand.ui.SquareRelativeLayout> </layout>

自定義 drawable xml
bg_block_tab:

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/item_block_tab_checked" android:state_checked="true" /><item android:drawable="@drawable/item_block_tab_unchecked" android:state_checked="false" /> </selector>

bg_blue:

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="@color/titlecolor" /> </shape>

bg_grid_press:

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_pressed="true"><shape><solid android:color="#f5f5f5" /></shape></item><item android:state_pressed="false"><shape><solid android:color="#f4f4f4" /></shape></item> </selector>

bg_white:

<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="@color/colorWhite"/> </shape>

適配器代碼:

package com.daobo.wand.ui.adapterimport androidx.recyclerview.widget.RecyclerView import com.daobo.wand.ui.FunctionItem import android.content.Context import android.view.ViewGroup import android.view.LayoutInflater import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.recyclerview.widget.RecyclerView.Adapter import com.daobo.wand.BR import com.daobo.wand.R import com.daobo.wand.databinding.LayoutGridItemBinding import com.daobo.wand.ui.viewbean.FuncItemViewBeanclass FunctionAdapter : Adapter<RecyclerView.ViewHolder> {private var data = ArrayList<FunctionItem>()private val context: Contextconstructor(context: Context, data: ArrayList<FunctionItem>) {this.context = contextif (data != null) {this.data = data}}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {return if (0 == viewType) {TitleViewHolder(DataBindingUtil.inflate(LayoutInflater.from(context),R.layout.layout_function_text, parent, false))} else {FunctionViewHolder(DataBindingUtil.inflate(LayoutInflater.from(context),R.layout.layout_grid_item, parent, false))}}override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {if (0 == getItemViewType(position)) {var binding : ViewDataBinding = DataBindingUtil.getBinding(viewHolder.itemView)!!binding.setVariable(BR.name, data[position].mName)binding.executePendingBindings()//val holder = viewHolder as TitleViewHolder//holder.text.setText(data[position].mName)} else {var binding : ViewDataBinding = DataBindingUtil.getBinding(viewHolder.itemView)!!val fi = data[position]var funcItemViewBean = FuncItemViewBean()funcItemViewBean.BtnImgSrc = if (fi.mIsSelect) R.drawable.item_block_selected else R.drawable.item_block_addfuncItemViewBean.IvImgSrc = context.resources.getIdentifier(fi.mImageUrl, "drawable",context.packageName)funcItemViewBean.Name = fi.mNamebinding.setVariable(BR.funcItem, funcItemViewBean)binding.executePendingBindings() else R.drawable.ic_block_add)var layoutGridItemBinding = binding as LayoutGridItemBindinglayoutGridItemBinding.btn.setOnClickListener {val f = data[position]if (!f.mIsSelect) {if (listener != null) {if (listener!!.add(f)) {f.mIsSelect = truenotifyDataSetChanged()}}}}}}override fun getItemViewType(position: Int): Int {return if (data[position].isTitle) 0 else 1}override fun getItemCount(): Int {return data.size}inner class TitleViewHolder(dataBinding: ViewDataBinding) : RecyclerView.ViewHolder(dataBinding.root)inner class FunctionViewHolder(dataBinding: ViewDataBinding) : RecyclerView.ViewHolder(dataBinding.root)interface OnItemAddListener {fun add(item: FunctionItem): Boolean}private var listener: OnItemAddListener? = nullfun setOnItemAddListener(listener: OnItemAddListener) {this.listener = listener} }

?

package com.daobo.wand.ui.adapterimport androidx.recyclerview.widget.RecyclerView import com.daobo.wand.ui.listener.ItemTouchHelperAdapter import com.daobo.wand.ui.FunctionItem import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import com.daobo.wand.BR import com.daobo.wand.R import com.daobo.wand.databinding.LayoutGridItemBinding import com.daobo.wand.ui.viewbean.FuncItemViewBean import java.util.* import kotlin.collections.ArrayListclass FunctionBlockAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>, ItemTouchHelperAdapter {private var data = ArrayList<FunctionItem>()private var context: Context? = nullconstructor(context: Context, data: ArrayList<FunctionItem>) {this.context = contextif (data != null) {this.data = data}}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {return FunctionViewHolder(DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.layout_grid_item, parent, false))}override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {val fi = data[position]var funcItemViewBean = FuncItemViewBean()funcItemViewBean.BtnImgSrc = R.drawable.item_block_deletefuncItemViewBean.IvImgSrc = context!!.resources.getIdentifier(fi.mImageUrl, "drawable",context!!.packageName)funcItemViewBean.Name = fi.mNamevar binding : ViewDataBinding = DataBindingUtil.getBinding(holder.itemView)!!binding.setVariable(BR.funcItem, funcItemViewBean)binding.executePendingBindings()var layoutGridItemBinding = binding as LayoutGridItemBindinglayoutGridItemBinding.btn.setOnClickListener {val fi = data.removeAt(position)if (listener != null) {listener!!.remove(fi)}notifyDataSetChanged()}}override fun getItemCount(): Int {return data.size}override fun onItemMove(holder: RecyclerView.ViewHolder, fromPosition: Int, targetPosition: Int) {if (fromPosition < data.size && targetPosition < data.size) {Collections.swap(data, fromPosition, targetPosition)notifyItemMoved(fromPosition, targetPosition)}}override fun onItemSelect(holder: RecyclerView.ViewHolder) {holder.itemView.scaleX = 0.8fholder.itemView.scaleY = 0.8f}override fun onItemClear(holder: RecyclerView.ViewHolder) {holder.itemView.scaleX = 1.0fholder.itemView.scaleY = 1.0f}override fun onItemDismiss(holder: RecyclerView.ViewHolder) {}inner class FunctionViewHolder(dataBinding: ViewDataBinding) : RecyclerView.ViewHolder(dataBinding.root)interface OnItemRemoveListener {fun remove(item: FunctionItem)}private var listener: OnItemRemoveListener? = nullfun setOnItemRemoveListener(listener: OnItemRemoveListener) {this.listener = listener} }

listener包下面定義的監聽:

package com.daobo.wand.ui.listenerimport androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerViewclass DefaultItemCallback : ItemTouchHelper.Callback {private var touchHelperAdapter: ItemTouchHelperAdapterconstructor(touchHelperAdapter: ItemTouchHelperAdapter) {this.touchHelperAdapter = touchHelperAdapter}override fun getMovementFlags(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder): Int {val dragFlags =ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT //允許上下左右的拖動return ItemTouchHelper.Callback.makeMovementFlags(dragFlags, 0)}override fun onMove(recyclerView: RecyclerView,viewHolder: RecyclerView.ViewHolder,target: RecyclerView.ViewHolder): Boolean {touchHelperAdapter.onItemMove(viewHolder,viewHolder.adapterPosition,target.adapterPosition)return true}override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)touchHelperAdapter.onItemSelect(viewHolder!!)}override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {if (!recyclerView.isComputingLayout)touchHelperAdapter.onItemClear(viewHolder)}override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}override fun isLongPressDragEnabled(): Boolean {return true}override fun isItemViewSwipeEnabled(): Boolean {return false} } package com.daobo.wand.ui.listenerimport androidx.recyclerview.widget.ItemTouchHelperclass DefaultItemTouchHelper : ItemTouchHelper {constructor(callback: ItemTouchHelper.Callback): super(callback) } package com.daobo.wand.ui.listenerimport androidx.recyclerview.widget.RecyclerViewinterface ItemTouchHelperAdapter {fun onItemMove(holder: RecyclerView.ViewHolder, fromPosition: Int, targetPosition: Int)fun onItemSelect(holder: RecyclerView.ViewHolder)fun onItemClear(holder: RecyclerView.ViewHolder)fun onItemDismiss(holder: RecyclerView.ViewHolder) }

?注意:在layout_function_item binding imageview 的src 資源,我們需要定義下:

package com.daobo.wand.ui.utilimport android.os.Build import android.view.View import android.widget.ImageView import androidx.annotation.RequiresApi import androidx.core.content.res.ResourcesCompat import androidx.databinding.BindingAdapterclass ImageBindingUtil {companion object {@BindingAdapter("android:src")@JvmStaticfun setSrc(view: ImageView, resId: Int) {view.setImageResource(resId)}@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)@JvmStatic@BindingAdapter("background")fun setBackground(view: View, id: Int) {//view.resources.getDrawable(id)view.background = ResourcesCompat.getDrawable(view.resources, id, null)}} }

binding adapter方法只需要全局static 聲明下,但是要使用注解@JvmStatic

工具類 用戶來初始化數據,且將數據保存到preferences中:

package com.daobo.wand.ui.utilimport android.content.Context import android.content.SharedPreferences import com.daobo.wand.ui.FunctionItem import com.daobo.wand.ui.TabItem import com.google.gson.Gson import com.google.gson.reflect.TypeToken import java.io.BufferedReader import java.io.IOException import java.io.InputStreamReaderclass SFUtils {private var context: Context? = nullprivate var sp: SharedPreferences? = nullvar tabItems : ArrayList<TabItem> = ArrayList()constructor(context: Context) {this.context = contextsp = context.getSharedPreferences("menudata", Context.MODE_PRIVATE)initData()}/*** 把已有的菜單數據 配置到* assets menuData 配置文件中*/fun getAllFunctionWithState(): ArrayList<FunctionItem> {var allData = sp!!.getString("allData", "")var functionItems = ArrayList<FunctionItem>()var tabItems: List<TabItem>? = nullif ("" == allData) {try {val ins = context!!.assets.open("menuData.txt")val isr = InputStreamReader(ins)val br = BufferedReader(isr)var str: String? = br.readLine()val sbuf = StringBuffer()while (str != null) {sbuf.append(str)}br.close()isr.close()ins.close()allData = sbuf.toString()tabItems = Gson().fromJson(allData, object : TypeToken<List<TabItem>>(){}.type)if (tabItems != null) {for (i in tabItems!!.indices) {val functionItem = FunctionItem(tabItems[i].getTabName(), true)functionItems.add(functionItem)functionItems.addAll(tabItems[i].getFunctionItems()!!)}}} catch (e: IOException) {e.printStackTrace()}} else {functionItems = Gson().fromJson(allData, object : TypeToken<List<FunctionItem>>(){}.type)}return functionItems}/*** 把用戶的選擇 保存到Preferences 文件* 即使 app 推出運行,內存數據清理掉* */fun getSelectFunctionItem(): ArrayList<FunctionItem> {val selData = sp!!.getString("selData", "")var functionItems: ArrayList<FunctionItem>? = nullfunctionItems = if ("" == selData) {ArrayList()} else {Gson().fromJson(selData, object : TypeToken<List<FunctionItem>>(){}.type)}return functionItems!!}fun getAllFunctionItems () : ArrayList<FunctionItem>{var functionItems = ArrayList<FunctionItem>()for (i in tabItems!!.indices) {val functionItem = FunctionItem(tabItems[i].getTabName(), true)functionItems.add(functionItem)functionItems.addAll(tabItems[i].getFunctionItems()!!)}return functionItems}fun getTabFunctionItems(): ArrayList<FunctionItem> {var tabItemsCount = 0 //用于標記之后滑動的位置var functionItems = ArrayList<FunctionItem>()for (i in tabItems!!.indices) {val functionItem =FunctionItem(tabItems[i].getTabName(), true, tabItemsCount)tabItemsCount += tabItems[i].getFunctionItems()!!.size + 1functionItems.add(functionItem)}return functionItems}fun getTabNames(): ArrayList<FunctionItem> {var allData = sp!!.getString("allData", "")var functionItems = ArrayList<FunctionItem>()var tabItems: List<TabItem>? = nullif ("" == allData) {try {val ins = context!!.assets.open("menuData.txt")val isr = InputStreamReader(ins)val br = BufferedReader(isr)var str: String? = br.readLine()val sbuf = StringBuffer()while (str != null) {sbuf.append(str)}br.close()isr.close()ins.close()allData = sbuf.toString()tabItems = Gson().fromJson(allData, object : TypeToken<List<TabItem>>(){}.type)if (tabItems != null) {var tabItemsCount = 0 //用于標記之后滑動的位置for (i in tabItems!!.indices) {val functionItem =FunctionItem(tabItems[i].getTabName(), true, tabItemsCount)tabItemsCount += tabItems[i].getFunctionItems()!!.size + 1functionItems.add(functionItem)}}} catch (e: IOException) { e.printStackTrace() }}//else{// functionItems = Gson().fromJson(allData, object : TypeToken<List<FunctionItem>>(){}.type)// }return functionItems}fun saveSelectFunctionItem(selData: List<FunctionItem>) {sp!!.edit().putString("selData", Gson().toJson(selData)).apply()}fun saveAllFunctionWithState(allData: List<FunctionItem>) {sp!!.edit().putString("allData", Gson().toJson(allData)).apply()}private fun initData () {var arrayList : ArrayList<FunctionItem> = ArrayList()arrayList.add(FunctionItem("充值中心",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("信用卡還款",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("生活繳費",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("城市服務",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("生活號",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("我的客服",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("我的快遞",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("醫療健康",false,"icon_home_selected","#86c751"))arrayList.add( FunctionItem("記賬本",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("城市一卡通",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("發票管家",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("螞蟻寶卡",false,"icon_home_selected","#86c751"))arrayList.add(FunctionItem("車主服務",false,"icon_home_selected","#86c751"))arrayList.add( FunctionItem("天天有料",false,"icon_home_selected","#86c751"))var tabItem : TabItem = TabItem("便民生活", arrayList)tabItems.add(tabItem)var arrayList1 : ArrayList<FunctionItem> = ArrayList()arrayList1.add(FunctionItem("余額寶",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("花唄",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("芝麻信用",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("螞蟻借唄",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("股票",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("保險服務",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("匯率換算",false,"icon_home_selected","#86c751"))arrayList1.add(FunctionItem("理財小工具",false,"icon_home_selected","#86c751"))var tabItem1 : TabItem = TabItem("財務管理",arrayList1)tabItems.add(tabItem1)var arrayList2 : ArrayList<FunctionItem> = ArrayList()arrayList2.add(FunctionItem("轉賬",false,"icon_home_selected","#86c751"))arrayList2.add(FunctionItem("紅包",false,"icon_home_selected","#86c751"))arrayList2.add(FunctionItem("AA收款",false,"icon_home_selected","#86c751"))arrayList2.add(FunctionItem("親密付",false,"icon_home_selected","#86c751"))arrayList2.add(FunctionItem("上銀匯款",false,"icon_home_selected","#86c751"))arrayList2.add(FunctionItem("話費卡轉讓",false,"icon_home_selected","#86c751"))var tabItem2 : TabItem = TabItem("資金往來",arrayList2)tabItems.add(tabItem2)var arrayList3 : ArrayList<FunctionItem> = ArrayList()arrayList3.add(FunctionItem("游戲中心",false,"icon_home_selected","#86c751"))arrayList3.add(FunctionItem("出境",false,"icon_home_selected","#86c751"))arrayList3.add(FunctionItem("彩票",false,"icon_home_selected","#86c751"))arrayList3.add(FunctionItem("人臉識別",false,"icon_home_selected","#86c751"))arrayList3.add(FunctionItem("獎勵金",false,"icon_home_selected","#86c751"))arrayList3.add(FunctionItem("世界杯",false,"icon_home_selected","#86c751"))var tabItem3 : TabItem = TabItem("購物娛樂",arrayList3)tabItems.add(tabItem3)var arrayList4 : ArrayList<FunctionItem> = ArrayList()arrayList4.add(FunctionItem("大學生活",false,"icon_home_selected","#86c751"))arrayList4.add(FunctionItem("愛心捐贈",false,"icon_home_selected","#86c751"))arrayList4.add(FunctionItem("螞蟻森林",false,"icon_home_selected","#86c751"))arrayList4.add(FunctionItem("螞蟻莊園",false,"icon_home_selected","#86c751"))arrayList4.add(FunctionItem("中小學",false,"icon_home_selected","#86c751"))arrayList4.add(FunctionItem("運動",false,"icon_home_selected","#86c751"))var tabItem4 : TabItem = TabItem("教育公益",arrayList4)tabItems.add(tabItem4)var arrayList5 : ArrayList<FunctionItem> = ArrayList()arrayList5.add(FunctionItem("淘票票",false,"icon_home_selected","#86c751"))arrayList5.add(FunctionItem("滴滴出行",false,"icon_home_selected","#86c751"))arrayList5.add(FunctionItem("餓了么外賣",false,"icon_home_selected","#86c751"))arrayList5.add(FunctionItem("天貓",false,"icon_home_selected","#86c751"))arrayList5.add(FunctionItem("淘寶",false,"icon_home_selected","#86c751"))arrayList5.add(FunctionItem("火車票機票",false,"icon_home_selected","#86c751"))var tabItem5 : TabItem = TabItem("第三方服務",arrayList5)tabItems.add(tabItem5)} }

要使用我的圖片資源,下載鏈接 。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

總結

以上是生活随笔為你收集整理的Kotlin binding+RecyclerView实现支付宝首页更多、应用编辑界面的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。