Android 在RecyclerView上使用权重,项目宽度开始表现出奇怪的行为

Android 在RecyclerView上使用权重,项目宽度开始表现出奇怪的行为,android,android-dialogfragment,Android,Android Dialogfragment,接下来的布局有什么问题 我假装在DialogFragment中包含一个RecyclerView,以列出复选框并处理检查 问题: 项目文本应填充屏幕内容。 在滚动时,项目排列到正确的位置。 dialog.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_wi

接下来的布局有什么问题

我假装在DialogFragment中包含一个RecyclerView,以列出复选框并处理检查

问题:

项目文本应填充屏幕内容。 在滚动时,项目排列到正确的位置。 dialog.xml:

<LinearLayout 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"
  android:orientation="vertical"
  android:paddingLeft="@dimen/spacing_large"
  android:paddingRight="@dimen/spacing_large"
  android:paddingTop="@dimen/spacing_large">

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/degrees_picker"
    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

  <ProgressBar
    android:id="@+id/degreesProgressBar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_margin="@dimen/spacing_large"
    android:indeterminate="true"
    android:visibility="gone" />

  <android.support.v7.widget.RecyclerView
    android:id="@+id/degreesRecyclerView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginTop="@dimen/spacing_medium"
    android:layout_weight="1"
    tools:listitem="@layout/degrees_item" />

  <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right">

    <Button
      android:id="@+id/degreesCancelButton"
      style="@style/Widget.AppCompat.Button.Borderless.Colored"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@string/cancel" />

    <Button
      android:id="@+id/degreesOkButton"
      style="@style/Widget.AppCompat.Button.Borderless.Colored"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@string/ok" />

  </LinearLayout>
</LinearLayout>
degrees_item.xml如果只有一个复选框,则会发生相同的情况:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:minHeight="?android:attr/listPreferredItemHeightSmall"
  android:orientation="horizontal">

  <TextView
    android:id="@+id/degreesItemTextView"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:layout_weight="1"
    android:gravity="center_vertical"
    tools:text="Degree tal tal tal tal tal tal tal tal tal tal tal tal tal tal tal tal" />

  <CheckBox
    android:id="@+id/degreesItemCheck"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="@dimen/spacing_medium" />

</LinearLayout>
适配器:

class DegreesAdapter(val preselectedItems: List<Degree>?) : RecyclerView.Adapter<DegreesAdapter.ViewHolder>(), SubtopicsItemListener {
  var items = listOf<Degree>()
    set(values) {
      field = values.map { CheckableDegree(it, checked = preselectedItems?.contains(it) == true) }
      notifyDataSetChanged()
    }

  val selectedItems get() = items.filter { (it as? CheckableDegree)?.checked == true }

  override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
    val inflater = LayoutInflater.from(parent?.context)
    val contactView = inflater.inflate(R.layout.degrees_item, parent, false)

    return ViewHolder(contactView, this)
  }

  override fun getItemCount() = items.size

  override fun getItemId(position: Int): Long {
    return items[position].id.toLong()
  }

  override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
    val degree = items[position]

    if (degree is CheckableDegree) {
      holder?.itemView?.degreesItemCheck?.isChecked = degree.checked
    }

    holder?.itemView?.degreesItemTextView?.text = degree.description
  }

  override fun onItemCheck(position: Int, checked: Boolean) {
    (items[position] as? CheckableDegree)?.checked = checked
  }

  class ViewHolder(itemView: View, listener: SubtopicsItemListener) : RecyclerView.ViewHolder(itemView) {
    init {
      itemView.degreesItemCheck.setOnCheckedChangeListener { _, isChecked ->
        listener.onItemCheck(layoutPosition, isChecked)
      }
    }
  }
}

interface SubtopicsItemListener {
  fun onItemCheck(position: Int, checked: Boolean)
}

class CheckableDegree(degree: Degree, var checked: Boolean = false)
  : Degree(degree.id, degree.description), Parcelable {
  companion object {
    @JvmField val CREATOR: Parcelable.Creator<CheckableDegree> = object : Parcelable.Creator<CheckableDegree> {
      override fun createFromParcel(source: Parcel): CheckableDegree = CheckableDegree(source)
      override fun newArray(size: Int): Array<CheckableDegree?> = arrayOfNulls(size)
    }
  }

  constructor(source: Parcel)
      : this(source.readParcelable<Degree>(Degree::class.java.classLoader),
      1 == source.readInt())

  override fun describeContents() = 0

  override fun writeToParcel(dest: Parcel, flags: Int) {
    super.writeToParcel(dest, flags)
    dest.writeInt((if (checked) 1 else 0))
  }
}
DegreesDialogFragment:

import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.medanswers.R
import com.medanswers.api.error.ApiError
import com.medanswers.api.repositories.user.Degree
import com.medanswers.base.MyActivity
import kotlinx.android.synthetic.main.degrees_dialog.*
import javax.inject.Inject

/**
 * Show the lists of subtopics
 */
class DegreesDialogFragment : DialogFragment(), DegreesDialogContract.View {

  val listener: Listener?
    get() = (activity as? Listener) ?: (targetFragment as? Listener)

  @Inject lateinit var presenter: DegreesDialogContract.Presenter

  companion object {
    val extrasPreselectedItems = "preselected_items"

    fun newInstance(preselectedItems: List<Degree>?): DegreesDialogFragment {
      val frag = DegreesDialogFragment()
      frag.arguments = Bundle().apply {
        preselectedItems?.let { putParcelableArray(extrasPreselectedItems, it.toTypedArray()) }
      }
      return frag
    }
  }

  override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, state: Bundle?): View? {
    return inflater?.inflate(R.layout.degrees_dialog, container)
  }

  override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    (activity as MyActivity).activityComponent.inject(this)

    @Suppress("UNCHECKED_CAST")
    val preselectedItems =
        (arguments.getParcelableArray(extrasPreselectedItems) as? Array<Degree>)?.toList()

    // calls initViews(preselectedItems)
    presenter.attach(this, preselectedItems)
  }

  override fun initViews(preselectedItems: List<Degree>?) {
    degreesRecyclerView.apply {
      layoutManager = LinearLayoutManager(activity)
      adapter = DegreesAdapter(preselectedItems)
    }

    degreesOkButton.setOnClickListener {
      (degreesRecyclerView?.adapter as? DegreesAdapter)?.selectedItems?.let {
        listener?.onDegreesDialogOkClick(it)
        dismiss()
      }
    }

    degreesCancelButton.setOnClickListener { this@DegreesDialogFragment.dismiss() }
  }

  override fun showItems(degrees: List<Degree>) {
    (degreesRecyclerView?.adapter as? DegreesAdapter)?.items = degrees
  }

  override fun showProgress() {
    degreesProgressBar.visibility = View.VISIBLE
  }

  override fun dismissProgress() {
    degreesProgressBar.visibility = View.GONE
  }

  override fun close(apiError: ApiError?) {
    apiError?.let { listener?.onDegreesDialogError(it) }
    dismiss()
  }

  interface Listener {
    fun onDegreesDialogOkClick(degrees: List<Degree>)
    fun onDegreesDialogError(apiError: ApiError)
  }
}
您需要根据如下代码设置DialogFragment width:

    WindowManager.LayoutParams p = getDialog().getWindow().getAttributes();
    p.width = ViewGroup.LayoutParams.MATCH_PARENT;
    p.height = ViewGroup.LayoutParams.MATCH_PARENT;
    getDialog().getWindow().setGravity(Gravity.CENTER);
    getDialog().getWindow().setAttributes(p);

您可以查看我的,并查看文件pickerdialogfragment.java以了解更多详细信息。

请出示您的视图夹。此外,您还可以编写:tools:listitem=@layout/degrees\u item,但您的项是item.xml。创建适配器的时候你没有弄错吗?@CoolMind我添加了适配器,是的,工具只是用于预览,不应该干扰真实的适配器为了理解宽度是如何变化的,我通常为元素degrees\u item.xml制作不同的背景色。例如,您可以将LinearLayout背景更改为绿色。可能您应该使用RelativeLayout而不是degrees_item.xml中的LinearLayout,在右侧有复选框。@chandil03如果项目中只有一个复选框,则结果相同。但问题不在于对话框宽度,而在于项目宽度。这些项目显示为宽度30,在滚动时,它们移动到宽度100,表示任何示例看起来都与@Caipivara相关,如果宽度增加,则应将其限制为最大宽度。我的意思是,你应该修正一个对话框的宽度。@CoolMind这个宽度不应该变大,应该是静态的,但是如果我把RecyclerView高度设置为200dp或其他修正值,这个问题就不会发生了,看起来重量搞乱了什么。@Caipivara,我通常会改变项目的背景色,以了解它们在布局中的位置和大小。在第一个布局中,布局_weight=1可能应用于宽度,而不是高度。您还可以在第一个布局的所有元素中设置width=match\u parent。也许可以尝试将RecyclerView包装到框架布局中。或者使用RelativeLayout代替垂直线性布局。