赞
踩
StateLayout(状态页)包含:加载中页面,错误页面,空页面,内含状态默认页面,支持自定义页面。
全局配置:
package com.example.tools.state_layout.widgets import android.view.View import androidx.annotation.LayoutRes /** * StateLayout全局配置 */ object StateConfig { @LayoutRes @JvmStatic var emptyLayoutRes = View.NO_ID @LayoutRes @JvmStatic var errorLayoutRes = View.NO_ID @LayoutRes @JvmStatic var loadingLayoutRes = View.NO_ID @LayoutRes @JvmStatic var retryIds: IntArray? = null private var mOnStateChangeListener: OnStateChangeListener? = null fun setOnStateChangeListener(listener: OnStateChangeListener) { mOnStateChangeListener = listener } fun getOnStateChangeListener(): OnStateChangeListener? { return mOnStateChangeListener } }
状态监听:
interface OnStateChangeListener {
fun showState(status: Int)
}
属性:
<declare-styleable name="StateLayout">
<attr name="empty_layout" format="reference" />
<attr name="loading_layout" format="reference" />
<attr name="error_layout" format="reference" />
</declare-styleable>
代码:
class StateLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { companion object { const val STATE_LOADING = 0xA001 const val STATE_EMPTY = 0xA002 const val STATE_ERROR = 0xA003 const val STATE_CONTENT = 0xA004 } // empty布局资源 @LayoutRes private var emptyLayoutRes = View.NO_ID get() = if (field == View.NO_ID) StateConfig.emptyLayoutRes else field // loading布局资源 @LayoutRes private var loadingLayoutRes = View.NO_ID get() = if (field == View.NO_ID) StateConfig.loadingLayoutRes else field // error布局资源 @LayoutRes private var errorLayoutRes = View.NO_ID get() = if (field == View.NO_ID) StateConfig.errorLayoutRes else field // 保存状态 private val stateInfoMap = ArrayMap<Int, View>() // 当前状态 private var currentState = STATE_CONTENT // 需要设置点击事件的id private var retryIds: IntArray? = null get() = field ?: StateConfig.retryIds private var mOnStateChangeListener: OnStateChangeListener? = null get() = field ?: StateConfig.getOnStateChangeListener() init { val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.StateLayout) emptyLayoutRes = a.getResourceId(R.styleable.StateLayout_empty_layout, View.NO_ID) loadingLayoutRes = a.getResourceId(R.styleable.StateLayout_loading_layout, View.NO_ID) errorLayoutRes = a.getResourceId(R.styleable.StateLayout_error_layout, View.NO_ID) a.recycle() } override fun onFinishInflate() { super.onFinishInflate() if (childCount != 1) { throw IllegalStateException("StateLayout必须只能有一个子View") } if (stateInfoMap.size == 0) { val view = getChildAt(0) setContentView(view) } } /** * 设置内容布局 */ private fun setContentView(contentView: View) { stateInfoMap[STATE_CONTENT] = contentView } /** * 设置点击事件 */ fun setRetryIds(@IdRes vararg ids: Int) { retryIds = ids } /** * 设置状态变化监听 */ fun setOnStateChangeListener(listener: OnStateChangeListener) { mOnStateChangeListener = listener } /** * 显示内容布局 */ fun showContent() { showState(STATE_CONTENT) } /** * 显示加载布局 */ fun showLoading() { showState(STATE_LOADING) } /** * 显示失败布局 */ fun showError() { showState(STATE_ERROR) } /** * 显示空布局 */ fun showEmpty() { showState(STATE_EMPTY) } /** * 显示视图 */ private fun showState(status: Int) { if (currentState == status) { return } val stateView = getStateView(status) for (i in stateInfoMap) { if (i.key != status) { val view = i.value hideStateView(view) } } showStateView(this, stateView, status) mOnStateChangeListener?.showState(status) currentState = status } /** * 获取状态视图 */ private fun getStateView(status: Int): View { val view = stateInfoMap[status] if (view != null) { return view } else { val layoutRes = when (status) { STATE_EMPTY -> emptyLayoutRes STATE_ERROR -> errorLayoutRes STATE_LOADING -> loadingLayoutRes STATE_CONTENT -> View.NO_ID else -> View.NO_ID } if (layoutRes == View.NO_ID) { when (status) { STATE_ERROR -> throw Resources.NotFoundException("请设置errorLayout") STATE_EMPTY -> throw Resources.NotFoundException("请设置emptyLayout") STATE_LOADING -> throw Resources.NotFoundException("请设置loadingLayout") STATE_CONTENT -> throw Resources.NotFoundException("请设置contentView") } } val view = LayoutInflater.from(context).inflate(layoutRes, this, false) stateInfoMap[status] = view return view } } /** * 隐藏视图 */ private fun hideStateView(view: View) { view.visibility = View.GONE } /** * 显示视图 */ private fun showStateView(container: StateLayout, view: View, status: Int) { if (container.indexOfChild(view) != -1) { view.visibility = View.VISIBLE } else { if (status == STATE_EMPTY || status == STATE_ERROR) { if (retryIds != null) { for (id in retryIds!!) { view.findViewById<View>(id).setOnClickListener { showLoading() } } } } container.addView(view) } } }
使用全局配置:
<com.example.tools.state_layout.widgets.StateLayout
android:id="@+id/state_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="加载成功" />
</com.example.tools.state_layout.widgets.StateLayout>
StateConfig.emptyLayoutRes = R.layout.state_empty StateConfig.errorLayoutRes = R.layout.state_error StateConfig.loadingLayoutRes = R.layout.state_loading StateConfig.retryIds = intArrayOf(R.id.state_msg, R.id.state_iv) StateConfig.setOnStateChangeListener(object : OnStateChangeListener { override fun showState(status: Int) { when (status) { StateLayout.STATE_LOADING -> { LogUtils.e("StateLayout", "显示加载页") postDelayed({ stateLayout.showContent() }, 2000L) } StateLayout.STATE_CONTENT -> { LogUtils.e("StateLayout", "显示内容页") } StateLayout.STATE_ERROR -> { LogUtils.e("StateLayout", "显示失败页") } StateLayout.STATE_EMPTY -> { LogUtils.e("StateLayout", "显示空页") } } } })
使用局部配置:
<com.example.tools.state_layout.widgets.StateLayout
android:id="@+id/state_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:empty_layout="@layout/state_empty"
app:error_layout="@layout/state_error"
app:loading_layout="@layout/state_loading">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="加载成功" />
</com.example.tools.state_layout.widgets.StateLayout>
stateLayout.setRetryIds(R.id.state_msg, R.id.state_iv) stateLayout.setOnStateChangeListener(object : OnStateChangeListener { override fun showState(status: Int) { when (status) { StateLayout.STATE_LOADING -> { LogUtils.e("StateLayout", "显示加载页") postDelayed({ stateLayout.showContent() }, 2000L) } StateLayout.STATE_CONTENT -> { LogUtils.e("StateLayout", "显示内容页") } StateLayout.STATE_ERROR -> { LogUtils.e("StateLayout", "显示失败页") } StateLayout.STATE_EMPTY -> { LogUtils.e("StateLayout", "显示空页") } } } })
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。