自定义视图 ProgressContainer 的问题

问题描述 投票:0回答:0

我有一个自定义视图 ProgessContainer,它可以处于三种状态(加载、错误、成功)。根据这些状态,显示不同的信息。但是,出于某种原因,layoutNotice 状态没有显示。加载和成功状态显示没有问题。我无法理解原因,这种状态根本就没有显示在屏幕上。有猜测可能是布局某处出错了

我试图在没有随机功能的情况下强制通知状态。它没有帮助

ProgressContainer.kt

private const val MAX_CHILD_COUNT = 3

class ProgressContainer @JvmOverloads constructor(
    context : Context,
    attrs: AttributeSet? = null,
    defStyleAttr : Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    private val layoutLoading : ViewGroup
    private val layoutNotice : ViewGroup

    init {
        val root = LayoutInflater.from(context).inflate(R.layout.view_progress_container, this, true)
        layoutLoading = root.findViewById(R.id.layoutLoading)
        layoutNotice = root.findViewById(R.id.layoutNotice)
    }

    override fun onViewAdded(child: View?) {
        super.onViewAdded(child)
        if(childCount > MAX_CHILD_COUNT) {
            throw IllegalStateException("Progress container can host only one direct child")
        }
    }

    private fun findContextView() : View? = children.firstOrNull {
        it.id != R.id.layoutLoading && it.id != R.id.layoutNotice
    }

    var state : State by Delegates.observable(State.Loading) { _, _, state ->
        when(state) {
            is State.Loading -> {
                layoutLoading.isVisible = true
                layoutNotice.isVisible = false
                findContextView()?.isVisible = false
            }
            is State.Notice -> {
                layoutLoading.isVisible = false
                layoutNotice.isVisible = true
                findContextView()?.isVisible = false

                val textViewError = layoutNotice.findViewById<TextView>(R.id.textViewError)
                textViewError.text = context.getString(state.errorResId)
                val textViewMessage = layoutNotice.findViewById<TextView>(R.id.textViewMessage)
                textViewMessage.text = context.getString(state.messageResId)

                val button = layoutNotice.findViewById<Button>(R.id.buttonRefresh)
                if (state.buttonHandler != null) {
                    button.isVisible = true
                    button.setOnClickListener(state.buttonHandler)
                } else {
                    button.isVisible = false
                }
            }
            is State.Success -> {
                layoutLoading.isVisible = false
                layoutNotice.isVisible = false
                findContextView()?.isVisible = true
            }
        }

    }
    sealed class State {
        object Loading : State()

        data class Notice(
            val errorResId: Int,
            val messageResId : Int,
            val buttonHandler: OnClickListener? = null
        ) : State()

        object Success : State()
    }
}

view_progress_container.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!--LOADING-->
    <FrameLayout
        android:id="@+id/layoutLoading"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">

        *here are some elements*
     
    </FrameLayout>
    <!--LOADING-->

   <!-- NOTICE-->
    <FrameLayout
        android:id="@+id/layoutNotice"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
       
           *here are some elements*

        </androidx.constraintlayout.widget.ConstraintLayout>

    </FrameLayout>
    <!-- NOTICE-->
    
</FrameLayout>

在片段中使用(只是随机生成状态)


class CatalogFragment : Fragment() {

    private lateinit var binding : FragmentCatalogBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentCatalogBinding.inflate(inflater,container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        refreshAll()
    }

    private fun refreshAll() {
        when((0..100).random()) {
            in 0..33 -> binding.progressContainer.state = ProgressContainer.State.Loading
            in 34..66 -> binding.progressContainer.state = ProgressContainer.State.Notice(
                R.string.catalog_notice_error,
                R.string.catalog_notice_error_message) {
                refreshAll()
            }
            in 67..100 -> binding.progressContainer.state = ProgressContainer.State.Success
        }
    }
}
android xml kotlin android-custom-view
© www.soinside.com 2019 - 2024. All rights reserved.