Android 在RecyclerView上使用权重,项目宽度开始表现出奇怪的行为
接下来的布局有什么问题 我假装在DialogFragment中包含一个RecyclerView,以列出复选框并处理检查 问题: 项目文本应填充屏幕内容。 在滚动时,项目排列到正确的位置。 dialog.xml: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
<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代替垂直线性布局。