如何在 Kotlin 的卡片视图中设置属性

Posted

技术标签:

【中文标题】如何在 Kotlin 的卡片视图中设置属性【英文标题】:How to set Attributes in a Card View in Kotlin 【发布时间】:2019-06-14 05:43:37 【问题描述】:

我正在设计一个 Feed,其中我希望以卡片的形式发布帖子,我使用 Google 的设计库实现了卡片。我已经创建了我的布局,但由于帖子将被动态获取,因此我想在 Kotlin 中动态创建我的布局。为此,我创建了一个函数,它将 Image、Title、Description 作为参数并返回一个 Card View 对象。

为了在 CardView 中设置属性,我尝试了 layoutParams,但使用它只会让我的应用崩溃

 val cardViewParam = cardView.layoutParams as CoordinatorLayout.LayoutParams

在这段代码中,我尝试了每种布局类型 Linear、Relative、Coordinator 甚至 ViewGroup,但我的应用每次都会崩溃。

这是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:layout_
            android:layout_
            tools:context=".Home"
            android:background="@color/DirtyWhite"
            android:scrollbars="none">
    <LinearLayout
            android:layout_
            android:layout_
            android:orientation="vertical"
            android:tag="FEED">

//This is the card view which I want to create dynamically

        <android.support.v7.widget.CardView android:layout_
                                            android:layout_
                                            android:layout_margin="5dp"
                                            android:elevation="50dp"
                                            app:cardCornerRadius="10dp">

            <LinearLayout android:layout_
                          android:layout_
                          android:orientation="vertical"
                          android:padding="10dp"
                          android:clipToPadding="false">

                <ImageView android:layout_
                           android:layout_
                           android:src="@drawable/sample"
                           android:scaleType="centerCrop"
                           android:layout_marginTop="-10dp"
                           android:layout_marginStart="-10dp"
                           android:layout_marginEnd="-10dp"
                           android:layout_marginBottom="-10dp"
                           android:adjustViewBounds="true"/>
                <TextView
                        android:layout_
                        android:layout_
                        style="@style/Base.TextAppearance.AppCompat.Title"
                        android:text="This is a  part of Material Design."
                        android:ellipsize="end"
                        android:maxLines="1"
                        android:layout_marginTop="16dp"
                />
                <TextView
                        android:layout_
                        android:layout_
                        style="@style/TextAppearance.AppCompat.Body2"
                        android:text="This is a  part of Material Design. This is a  part of Material Design. This is a  part of Material Design. "
                        android:ellipsize="end"
                        android:textColor="@color/realGray"
                        android:maxLines="2"
                        android:layout_marginTop="8dp"
                />

                <RelativeLayout android:layout_
                                android:layout_marginTop="8dp"
                                android:layout_>
                    <RatingBar android:layout_ android:layout_
                               android:numStars="5"
                               android:rating="3"
                               android:isIndicator="true"
                               android:layout_alignParentLeft="true"
                               android:layout_alignParentStart="true"
                               android:layout_centerInParent="true"
                               style="@style/Base.Widget.AppCompat.RatingBar.Small"/>
                    <LinearLayout android:layout_ android:layout_
                                  android:layout_alignParentRight="true"
                                  android:layout_alignParentEnd="true">
                        <Button android:layout_ android:layout_
                                android:background="@drawable/ic_favorite_border_black_24dp"
                                android:minHeight="30dp"
                                android:minWidth="30dp"
                                android:layout_marginRight="15dp"
                                android:layout_marginEnd="15dp"
                        />
                        <Button android:layout_
                                android:layout_
                                android:text="Order Now"
                                android:background="@drawable/rounded_card_button_small"
                                android:textColor="@color/DirtyWhite"
                                android:minHeight="0dp"
                                android:minWidth="0dp"
                                android:padding="5dp"/>
                    </LinearLayout>


                </RelativeLayout>

            </LinearLayout>

        </android.support.v7.widget.CardView>


    </LinearLayout>
</ScrollView>

我尝试了这段代码来动态创建布局: (注意:此代码仅用于创建基本卡片,不包括评分栏和其他操作按钮)

fun createAdsPost(view: View, photo: ImageView, titleText: String, descText: String): CardView 

    val cardView = CardView(view.context)
    val cardViewParam = cardView.layoutParams as CoordinatorLayout.LayoutParams
    cardView.layoutParams = cardViewParam
    cardViewParam.width = LinearLayout.LayoutParams.MATCH_PARENT
    cardViewParam.height = LinearLayout.LayoutParams.WRAP_CONTENT
    cardViewParam.setMargins(dpToPx(5, view), dpToPx(5, view), dpToPx(5, view), dpToPx(5, view))
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
        cardView.elevation = dpToPx(50, view).toFloat()
    
    cardView.apply 
    radius = dpToPx(10, view).toFloat()
        this.layoutParams = cardViewParam

    
    val linear1 = LinearLayout(view.context)
     linear1.orientation = LinearLayout.VERTICAL
     linear1.setPadding(dpToPx(10, view), dpToPx(10, view), dpToPx(10, view), dpToPx(10, view))
     linear1.clipToPadding = false
     val linear1Param = linear1.layoutParams as LinearLayout.LayoutParams
     linear1Param.width = LinearLayout.LayoutParams.MATCH_PARENT
     linear1Param.height = LinearLayout.LayoutParams.WRAP_CONTENT
     linear1.layoutParams = linear1Param
     photo.scaleType = ImageView.ScaleType.CENTER_CROP
     photo.adjustViewBounds = true
     val photoParams = photo.layoutParams as LinearLayout.LayoutParams
     photoParams.apply 
         width = LinearLayout.LayoutParams.MATCH_PARENT
         height = dpToPx(180, view)
         topMargin = dpToPx(-10, view)
         bottomMargin = dpToPx(-10, view)
     
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) 
         photoParams.marginStart = dpToPx(-10, view)
         photoParams.marginEnd = dpToPx(-10, view)
     
     linear1.addView(photo)
      val title = TextView(view.context) 
       title.apply 
           ellipsize = TextUtils.TruncateAt.END
           maxLines = 1
           text = titleText
       
       val titleTextParams = title.layoutParams as LinearLayout.LayoutParams
       titleTextParams.apply 
           width = LinearLayout.LayoutParams.MATCH_PARENT
           height = LinearLayout.LayoutParams.WRAP_CONTENT
           topMargin = dpToPx(16, view)
       
      linear1.addView(title)
     val desc = TextView(view.context)
      desc.apply 
          ellipsize = TextUtils.TruncateAt.END
          maxLines = 2
          text = descText
          setTextColor(Color.parseColor("#626567"))
      
      val descTextParams = desc.layoutParams as LinearLayout.LayoutParams
      descTextParams.apply 
          width = LinearLayout.LayoutParams.MATCH_PARENT
          height = LinearLayout.LayoutParams.WRAP_CONTENT
          topMargin = dpToPx(8, view)

      
     linear1.addView(desc)
    cardView.addView(linear1)

    return cardView

当我使用这些代码时,我的应用程序崩溃了。我尝试调试我的代码,发现第一个错误出现在 CardView 的layoutParams 中。 总之,我想知道如何在卡片视图中设置属性 另外,请告诉这是创建动态布局的唯一方法还是有更有效的方法。我是 Android 开发新手。

【问题讨论】:

【参考方案1】:

我想建议一件事,如果您的要求是动态创建视图,那么您只需尝试一件事:

1) 为您的动态视图制作一个单独的布局文件 2) 使用以下方法扩展该布局:

val layoutInflater = getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
    layoutInflater!!.inflate(R.layout.your_layout_file)

3) 现在您将拥有视图,然后您只需要使用以下方式访问布局视图:

view.findViewById(you view id)

4) 现在您将能够轻松地动态创建和访问您的视图

Note:

getContent() : will come according to your usage on fragment or in activity, so need to change it accordingly
same as inflate method, use parameter according to your requirement

【讨论】:

你是对的!我认为这是添加动态创建的布局的更好方法。我以前不知道这个概念。谢谢你的回答。另外,你能告诉我我的哪个错误导致对这个问题投反对票 @PrathamVaidya 您的问题标题可能与您正在寻找答案的问题无关,您只在 CardView 中编写了 setAttribute 但您的问题与此无关,因此可能因为这个原因才有可能。 好的,我会在接下来的问题中尝试改进【参考方案2】:

您将LayoutParams 转换为CoordinatorLayout.LayoutParams,而您正在动态创建一个没有父视图的视图,我认为这就是问题所在。

如果您是动态创建视图,那么您也应该根据其父容器创建新的LayoutParams

例如,如果您想在LinearLayout 中添加CardView,则LayoutParams 应如下所示:

val cardView = CardView(view.context)
val cardViewParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).also 
  it.setMargins(dpToPx(5, view), dpToPx(5, view), dpToPx(5, view), dpToPx(5, view))


cardView.apply 
        radius = dpToPx(10, view).toFloat()
            this.layoutParams = cardViewParam

        
...
...

val linear1 = LinearLayout(view.context)
val linear1Param = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT)
...
...
cardView.addView(linear1)

对于linear1,我们采用FrameLayout.LayoutParams,因为在我们的例子中,我们将把它添加为CardView 的子代,CardView 是扩展的FrameLayout

【讨论】:

是的,您指出了正确的错误。我尝试了您的代码并且它有效,但是由于某种原因,负边距没有应用于视图,这就是为什么我的动态布局看起来不像 xml 创建的布局,即使这是一个漫长的过程,所以我改用了 Inflators。感谢您的回答,即使您的答案是正确的

以上是关于如何在 Kotlin 的卡片视图中设置属性的主要内容,如果未能解决你的问题,请参考以下文章

如何找出当前是不是在 SwiftUI 中选择了视图

如何根据内容自动调整卡片视图的大小

如何禁用 Kotlin Android 扩展插件生成合成视图属性

Kotlin DSL 中的 gradle 额外属性是如何设置的?

创建卡片时如何在 recyclerview (cardview) 中添加日期。 (卡片创建日期)

如何将参数传递给 DataTrigger?