Kotlin在1.4.20-M2版本中弃用了Kotlin Android Extension,先前开发时没特别注意到这个资讯,只有觉得Android Studio自某版本开始没有自动加入apply plugin: 'kotlin-android-extensions'
感到有些奇怪。最近了解了一下相关资讯後决定把目前在做的专案都改成使用ViewBinding了
在Gradle内加入
android {
// ...
buildFeatures {
viewBinding true
}
// ...
}
并将有使用到kotlinx.android.synthetic的import都移除掉。
先宣告Binding物件,Binding物件的名称会根据layout.xml的名称来自动产生,比如activity_main.xml就会产生为ActivityMainBinding。
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
接着在onCreate中呼叫Binding物件的inflate方法来初始化,并且将setContentView中传入的内容改为inflate後的root。
最後使用到layout内的View时需从binding呼叫。
原本:
public fun showLoading(msg: String) {
loadingLayout.visibility = View.VISIBLE
loadingMsg.text = msg
}
修改後:
public fun showLoading(msg: String) {
binding.loadingLayout.visibility = View.VISIBLE
binding.loadingMsg.text = msg
}
class SearchArticleFragment : Fragment() {
private var _binding: FragmentSearchArticleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = FragmentSearchArticleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Fragment的ViewBinding物件在inflate时需传入所属的parent。另外要注意在onDestroyView的时候将_binding
设回null,避免Memory Leak。
在RecyclerView.Adapter中使用时需要修改ViewHolder,将原本传入View的部分改为传入ViewBinding物件,super的部分则传入binding.root即可:
inner class ViewHolder(private val binding: ItemSearchArticleResultBinding) :
RecyclerView.ViewHolder(binding.root) {
init {
itemView.setOnClickListener {
onArticleClickListener?.invoke(articleList[adapterPosition])
}
}
fun bindView(article: Article) {
binding.number.text = article.number
binding.author.text = article.author
binding.title.text = article.title
binding.date.text = article.date
}
}
RecyclerView.onCreateViewHolder对应修改:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = ViewHolder(
ItemSearchArticleResultBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
)
在Day09时我用了PopupWindow来显示看板的搜寻结果,过程中有另外inflate子View的部分,这边在使用ViewBinding时也需要做一点修改,原本的程序码连结内有就不重复贴了。
// ...
val boardResultBinding = LayoutSearchBoardResultBinding.inflate(
LayoutInflater.from(requireContext()),
null,
false
)
val height = if (boardList.isEmpty()) {
boardResultBinding.noResultLabel.visibility = View.VISIBLE
boardResultBinding.recyclerView.visibility = View.GONE
120f.dpToPx(requireContext())
} else {
val adapter = SearchBoardResultAdapter(boardList)
adapter.onBoardClickListener = { board ->
popupWindow?.dismiss()
binding.searchBoardInput.setText(board)
}
boardResultBinding.recyclerView.setHasFixedSize(true)
boardResultBinding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
boardResultBinding.recyclerView.adapter = adapter
360f.dpToPx(requireContext())
}
popupWindow = PopupWindow(
boardResultBinding.root, // view
ViewGroup.LayoutParams.MATCH_PARENT, // width
height, // height
true // focusable
)
// ...
<<: 【从实作学习ASP.NET Core】Day21 | 前台 | 用检视元件建立选单
>>: [Day 20] Facial Recognition: OpenCV + Dlib可以一次满足
取得信用帐户资讯 # futopt_account - 期货,选择权帐号 account_marg...
昨天我们已经把登入画面做好了,大家有没有觉得万事起头难呢? 既然我们已经有登入画面了,当然要有注册...
前言 上集我们介绍到 Enum 基础用法,今天将来讲解其它用法。 字串列举(String enum)...
嗨,我是Bear。 遵守在Day30时与自己的约定,於年前写完所有设计模式。 稍晚会将目录更新至Da...
可以先来说说现在外面的AI工作需求, 从104来看可以发现每个AI的工作几乎都有至少10个人在应徵,...