根据@Fletcher Johns的答案,我得出了以下结论:
- 自定义布局
- 可以从XML中膨胀
- 能够保存/还原直接和间接子视图。我改进了@Fletcher Johns的答案,将ids保存在String->Id映射中,而不是IntArray。
- 唯一的小缺点是您必须预先声明可保存的子视图。
open class AddressView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
protected lateinit var countryInputLayout: TextInputLayout
protected lateinit var countryAutoCompleteTextView: CountryAutoCompleteTextView
protected lateinit var cityInputLayout: TextInputLayout
protected lateinit var cityEditText: CityEditText
protected lateinit var postCodeInputLayout: TextInputLayout
protected lateinit var postCodeEditText: PostCodeEditText
protected lateinit var streetInputLayout: TextInputLayout
protected lateinit var streetEditText: StreetEditText
init {
initView()
}
private fun initView() {
val view = inflate(context, R.layout.view_address, this)
orientation = VERTICAL
countryInputLayout = view.findViewById(R.id.countryInputLayout)
countryAutoCompleteTextView = view.findViewById(R.id.countryAutoCompleteTextView)
streetInputLayout = view.findViewById(R.id.streetInputLayout)
streetEditText = view.findViewById(R.id.streetEditText)
cityInputLayout = view.findViewById(R.id.cityInputLayout)
cityEditText = view.findViewById(R.id.cityEditText)
postCodeInputLayout = view.findViewById(R.id.postCodeInputLayout)
postCodeEditText = view.findViewById(R.id.postCodeEditText)
}
private val childrenToSave get() = mapOf<String, View>(
"coutryIL" to countryInputLayout,
"countryACTV" to countryAutoCompleteTextView,
"streetIL" to streetInputLayout,
"streetET" to streetEditText,
"cityIL" to cityInputLayout,
"cityET" to cityEditText,
"postCodeIL" to postCodeInputLayout,
"postCodeET" to postCodeEditText,
)
private var viewIds: HashMap<String, Int>? = null
override fun onSaveInstanceState(): Parcelable? {
val bundle = Bundle()
bundle.putParcelable(SUPER_INSTANCE_STATE, super.onSaveInstanceState())
if (viewIds == null) {
childrenToSave.values.forEach { view -> view.id = generateViewId() }
viewIds = HashMap<String, Int>(childrenToSave.mapValues { (key, view) -> view.id })
}
bundle.putSerializable(STATE_VIEW_IDS, viewIds)
return bundle
}
override fun onRestoreInstanceState(state: Parcelable?) {
val bundle = state as Bundle
viewIds = bundle.getSerializable(STATE_VIEW_IDS) as HashMap<String, Int>
if (viewIds != null) {
viewIds!!.forEach { (key, id) -> childrenToSave[key]!!.id = id }
}
super.onRestoreInstanceState(bundle.getParcelable(SUPER_INSTANCE_STATE))
}
companion object {
private const val SUPER_INSTANCE_STATE = "saved_instance_state_parcelable"
private const val STATE_VIEW_IDS = "state_view_ids"
}
}
onSaveInstanceState
返回了一个Bundle,为什么onRestoreInstanceState
不会被调用呢? - QwertieOnRestoreInstance
是继承而来的。我们不能改变头文件。Parcelable
只是一个接口,Bundle
是其实现。 - Kobor42