【问题标题】:Dynamic TextView not displaying properly动态 TextView 无法正确显示
【发布时间】:2022-01-01 20:29:20
【问题描述】:

我正在循环中动态生成一些 TextView。它们正在显示,但我无法在它们之间制造差距。它们显示为一行而不是单独的行。

    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    >

        <LinearLayout

            android:id="@+id/ll"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingLeft="18dp"
            android:paddingRight="18dp"
            android:paddingTop="60dp"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:focusableInTouchMode="true"
            android:orientation="vertical">

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

tviewlayout.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/light"
    android:textAlignment="gravity"
    android:padding="10dp"
    android:layout_margin="10dp"
    android:textSize="20sp" />

Java 代码

LinearLayout linearLayout =  (LinearLayout) binding.ll;
                for (int i=0; i<arrSplit.length; i++)
                {
                    TextView tv = (TextView)getLayoutInflater().inflate(R.layout.tviewlayout, null);
                    tv.setText(arrSplit[i]);
                    tv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                    linearLayout.addView(tv);
                }

【问题讨论】:

  • 如果你将任何东西放入一个约束布局(在本例中是你的 LinearLayout),你需要定义它的约束。将 LL 的所有 4 个约束设置为“父”,事情应该会更好。还将 LL 的 layout_widthlayout_height 设置为“0dp”。这告诉 Android 它应该使用给定的约束。
  • 移除约束布局!
  • 你能提供一张你得到的照片吗
  • @Zain 我添加了一张照片
  • 那么,我认为每个训练行都是LinearLayout 中的TextView?如果是这样,这是意料之中的......你能展示你期望看到的东西吗?所以不会有混乱

标签: android android-layout


【解决方案1】:

我建议将 recylerview 用于此类目的。它更加高效和动态。示例在 Kotlin

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/consRideInfo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/10dp"
    android:padding="@dimen/10dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/incActionBar">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rcvList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="0dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:itemCount="3"
        tools:listitem="@layout/row_item" />

</androidx.constraintlayout.widget.ConstraintLayout>

关于Activity定义适配器

 private var adapter: GeneralAdapter<DataModel, MainActivity>? = null
 private val list: ArrayList<DataModel> = ArrayList()

在 onCreate 中

 adapter = GeneralAdapter(R.layout.row_item, list, this)
 binding.rcvList.adapter = adapter

并创建适配器用于显示

class GeneralAdapter<D, F>(
    val layoutId: Int,
    private val arrayList: ArrayList<D>,
    val listener: F
) : RecyclerView.Adapter<GeneralAdapter.GeneralHolder<D, F>>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GeneralHolder<D, F> {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding: ViewDataBinding =
            DataBindingUtil.inflate(layoutInflater, layoutId, parent, false)

        return GeneralHolder(binding, listener)
    }

    override fun getItemCount(): Int = arrayList.size

    override fun onBindViewHolder(holder: GeneralHolder<D, F>, position: Int) {
        holder.bind(arrayList[position])
    }

    class GeneralHolder<D, F>(
        private val binding: ViewDataBinding,
        val listener: F
    ) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(data: D) {
            binding.setVariable(BR.item, data)
            binding.setVariable(BR.presenter, listener)
            binding.executePendingBindings()
        }
    }
}

【讨论】:

    【解决方案2】:

    我想在每个 TextView 之间创建间隙,以便它们看起来是分开的。现在都被蓝色背景覆盖了

    您可以为每个TextViews 添加一个以像素为单位的边距:

    LinearLayout linearLayout =  (LinearLayout) binding.ll;
    
    for (int i=0; i<arrSplit.length; i++) {
        TextView tv = (TextView)getLayoutInflater().inflate(R.layout.tviewlayout, null);
        tv.setText(arrSplit[i]);
        tv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) tv.getLayoutParams();
        params.bottomMargin = (int) getPx(100); // adding 100dp gap between TextViews
        linearLayout.addView(tv);
    }
    
    
    
    /*
     * Convert dp value to pixel
     * */
    private float getPx(float dp) {
        return TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                dp,
                getResources().getDisplayMetrics());
    }
    

    更新

    你能告诉我如何使用 RecyclerView 实现同样的效果吗?

    这是一个演示:

    main_activity.xml:

    <?xml version="1.0" encoding="utf-8"?>
    
    <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/rvList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" />
    

    list_item.xml:包含您的TextView 的模板 使用android:layout_marginBottom 在两个连续的 TextView 之间添加所需的边距

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/tvColorName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="32dp"
        android:textSize="18sp" />
    

    适配器:

    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.CustomViewHolder> {
    
        private List<String> mColors;
    
        // Constructor
        RecyclerAdapter(List<String> colors) {
            this.mColors = colors;
        }
    
    
        @NonNull
        @Override
        public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
            View listItem = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.list_item, parent, false);
            return new CustomViewHolder(listItem);
        }
    
        @Override
        public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) {
            String color = mColors.get(position);
            holder.tvColorName.setText(color);
        }
    
        @Override
        public int getItemCount() {
            return mColors.size();
        }
    
    
        class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
    
            TextView tvColorName;
    
            CustomViewHolder(@NonNull View listItem) {
                super(listItem);
                // caching views
                tvColorName = listItem.findViewById(R.id.tvColorName);
            }
    
        }
    
    
    }
    
    

    活动:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Building RecyclerView
            RecyclerView recyclerView = findViewById(R.id.rvList);
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
    
            // Building RecyclerAdapter
            RecyclerAdapter adapter = new RecyclerAdapter(this, getColors());
            recyclerView.setAdapter(adapter);
    
        }
        
        
        private ArrayList<String> getColors() {
            ArrayList<String> colors = new ArrayList<>();
            colors.add("Red");
            colors.add("White");
            colors.add("Green");
            colors.add("Purple");
            colors.add("Yellow");
            colors.add("Blue");
            colors.add("Black");
            colors.add("Brown");
            colors.add("Magenta");
            colors.add("Cyan");
            colors.add("Gray");
            colors.add("Orange");
            return colors;
        }
        
    }
    
    

    【讨论】:

    • 但我建议将此方法更改为 RecyclerView 以具有回收视图功能
    • 你能告诉我如何使用 RecyclerView 实现同样的效果吗?
    • @John Sure.. 请检查更新的答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2012-11-20
    • 2012-01-06
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多