代码之家  ›  专栏  ›  技术社区  ›  J. Doe

以编程方式创建UI时,不会显示回收项目

  •  0
  • J. Doe  · 技术社区  · 2 年前

    出于某种原因,我不想使用XML,我只想以编程方式创建我的UI。我现在的问题是,无论我提供多少元素,我的视图都不会显示在屏幕上。这是我的屏幕:

    enter image description here

    我不明白为什么它没有显示出来。我使用以下命令将一个非常简单的视图添加到父视图的上下文中 ConstraintLayout 我甚至提供了一个固定的高度。

    请注意,我正在使用 AndroidView 因为我想在Jetpack Compose中使用这个RecyclerView。但我不认为这会导致这个问题。

    我添加了下面的代码,我也在这里上传了项目(运行应用程序会立即显示问题): https://github.com/Jasperav/RecyclerView/tree/main

    fun createChat(context: Context): ConstraintLayout {
        val recyclerView = createRecyclerView(context)
    
        return recyclerView
    }
    
    fun createRecyclerView(context: Context): ConstraintLayout {
        val constraintLayout = createConstraintLayout(context)
        val parent = applyDefaults(constraintLayout.constraintLayout, View(context), MATCH_PARENT, MATCH_PARENT)
    
        parent.setBackgroundColor(context.getColor(R.color.yellow))
    
        constraintLayout.fill(parent, constraintLayout.constraintLayout)
    
        val recyclerView = applyDefaults(constraintLayout.constraintLayout, RecyclerView(context), MATCH_PARENT, MATCH_PARENT)
    
        recyclerView.setBackgroundColor(context.getColor(R.color.purple_500))
    
        constraintLayout.fill(recyclerView, parent)
    
        val shapeDrawable = MaterialShapeDrawable()
    
        shapeDrawable.fillColor = ColorStateList.valueOf(context.getColor(R.color.teal_200))
        shapeDrawable.setStroke(5f, context.getColor(R.color.red))
    
        recyclerView.background = shapeDrawable
        recyclerView.adapter = ChatAdapter()
        recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
    
        return constraintLayout.constraintLayout
    }
    
    class ChatCell : View {
        private val textView: TextView
    
        constructor(parent: ViewGroup) : super(parent.context) {
            println("Created")
    
            val constraintLayout = createConstraintLayout(context)
    
            textView = applyDefaults(constraintLayout.constraintLayout, TextView(context), MATCH_PARENT, MATCH_PARENT)
    
            constraintLayout.constraintSet.constrainHeight(textView.id, 100)
            constraintLayout.constraintSet.applyTo(constraintLayout.constraintLayout)
    
            constraintLayout.fill(textView, constraintLayout.constraintLayout)
    
            textView.text = "test"
            textView.setBackgroundColor(context.getColor(R.color.red))
            setBackgroundColor(context.getColor(R.color.red))
        }
    
        fun x() {
        }
    }
    
    class ViewHolderTemp : RecyclerView.ViewHolder {
        val chatCell: ChatCell
    
        constructor(chatCell: ChatCell) : super(chatCell) {
            this.chatCell = chatCell
        }
    }
    
    class ChatAdapter : RecyclerView.Adapter<ViewHolderTemp>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderTemp {
            val chatCell = ChatCell(parent)
    
            return ViewHolderTemp(chatCell)
        }
    
        override fun getItemCount() = 2
    
        override fun onBindViewHolder(holder: ViewHolderTemp, position: Int) {
            holder.chatCell.x()
        }
    }
    
    class Layout(val constraintLayout: ConstraintLayout, val constraintSet: ConstraintSet)
    
    fun createConstraintLayout(context: Context): Layout {
        val c = ConstraintLayout(context).apply {
            id = View.generateViewId()
            layoutParams = ViewGroup.LayoutParams(
                MATCH_PARENT,
                MATCH_PARENT,
            )
        }
    
        val set = ConstraintSet()
    
        set.clone(c)
    
        return Layout(c, set)
    }
    
    
    fun <T: View> applyDefaults(constraintLayout: ConstraintLayout, view: T, width: Int, height: Int): T {
        view.id = View.generateViewId()
        view.layoutParams = ConstraintLayout.LayoutParams(
            width,
            height,
        )
    
        constraintLayout.addView(view)
    
        return view
    }
    
    fun Layout.fill(view: View, inView: View) {
        val constraintSet = ConstraintSet()
    
        constraintSet.clone(constraintLayout)
    
        constraintSet.connect(view.id, ConstraintSet.LEFT, inView.id, ConstraintSet.LEFT);
        constraintSet.connect(view.id, ConstraintSet.TOP, inView.id, ConstraintSet.TOP);
        constraintSet.connect(view.id, ConstraintSet.RIGHT, inView.id, ConstraintSet.RIGHT);
        constraintSet.connect(view.id, ConstraintSet.BOTTOM, inView.id, ConstraintSet.BOTTOM);
    
        constraintSet.applyTo(constraintLayout)
    }
    
    @Composable
    fun GreetingX() {
        AndroidView(factory = { context ->
            createChat(context)
        })
    }
    
    @Preview(showBackground = true)
    @Composable
    fun DefaultPreviewX() {
        RecyclverTestTheme {
            GreetingX()
        }
    }
    
    0 回复  |  直到 2 年前
        1
  •  1
  •   Cheticamp    2 年前

    你的班级 ChatCell 不是做你想做的事。下面是一个版本,我认为,它做了你想要的事。我加入了评论来解释正在发生的事情。

    class ChatCell(parent: ViewGroup) : ConstraintLayout(parent.context) {
        private val textView: TextView
    
        init {
            // LayoutParams for ConstraintLayout within the RecyclerView
            layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT)
    
            // Create the TextView within the ConstraintLayout and add it to the layout.
            textView = TextView(parent.context).apply {
                id = View.generateViewId()
                // Always use ConstraintSet.MATCH_CONSTRAINT (size = 0) with appropriate constraints
                // for MATCH_PARENT within a ConstraintLayout.
                layoutParams = LayoutParams(ConstraintSet.MATCH_CONSTRAINT, 100)
                setBackgroundColor(context.getColor(R.color.white))
            }
            addView(textView)
    
            // Now that the TextView is added to the ConstraintLayout, we can constrain it.
            // Note that the TextView MUST be added to the ConstraintLayout before we create
            // the ConstraintSet.
            val cs = ConstraintSet()
            cs.clone(this)
            cs.connect(
                textView.id,
                ConstraintSet.START,
                ConstraintSet.PARENT_ID,
                ConstraintSet.START
            )
            cs.connect(textView.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END)
            cs.applyTo(this)
    
            // Our item view is now created and will be drawn appropriately within the RecyclerView.
        }
    
        // Here is where we bind the text to the item view's TextView.
        fun x(text: String) {
            textView.text = text
        }
    }
    

    这个 onBindViewHolder() 函数与新代码一起工作时看起来像下面这样:

    override fun onBindViewHolder(holder: ViewHolderTemp, position: Int) {
        holder.chatCell.x("Text at position $position")
    }
    

    这是模拟器上的应用程序:

    enter image description here

    更好的函数声明 ChatCell 自定义视图将是

    class ChatCell @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null
    ) : ConstraintLayout(context, attrs) 
    

    这将允许在XML中使用该类,并消除Android Studio对类声明方式的抱怨。