Android 布局权重总和未正确拆分
Android Layout Weight Sum Not Splitting Properly
我的应用程序上的一个页面有一个 table 布局页面,其中一行似乎不起作用。我的目标是在左侧单元格和右侧单元格之间平均拆分页面。左侧单元格包含一个字符串,右侧单元格包含一个图像和字符串。我尝试使用 weightSum 这样做。左侧单元格的权重为 4/8,右侧单元格为线性布局,其中图像的权重为 1/8,字符串的权重为 3/8。但是,在布局中,左侧单元格占据了行的绝大部分,大约 75%,我不确定为什么。
我下面这一行尝试了几乎相同的事情,但没有同样的问题。
我的 xml(因相关性而删减):
<TableRow
android:layout_width="match_parent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Class"
android:id="@+id/classTextView"
android:layout_marginTop="14dp"
android:layout_weight="1"
android:gravity="center"/>
<LinearLayout>
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_height="match_parent"
android:background="#663300"/>
<ImageView
tools:ignore="ContentDescription"
android:id="@+id/classicon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/barbarianicon50"
android:layout_gravity="end"
android:layout_weight="1"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Class Value"
android:id="@+id/classValueView"
android:layout_marginTop="14dp"
android:layout_weight="3"
android:gravity="left"/>
</LinearLayout>
</TableRow>
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="#663300"/>
<TableRow android:layout_width="match_parent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Strength"
android:id="@+id/strengthTextView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
<LinearLayout>
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_weight="0"
android:layout_height="match_parent"
android:background="#663300"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Strength Value"
android:id="@+id/strengthValView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Intelligence"
android:id="@+id/intelligenceTextView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
<LinearLayout>
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_weight="0"
android:layout_height="match_parent"
android:background="#663300"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Intelligence Value"
android:id="@+id/intelligenceValView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
</LinearLayout>
</TableRow>
第一 table 行是有问题的行 - 它应该在左右单元格之间平均分配,但大部分偏向右侧。
第二个 table 行是它正常工作的一个例子 - 这一行有 2 对单元格,但是每个单元格,以及每对单元格都正确地平均分配了它们之间的宽度。
我不明白为什么第一个不起作用。感谢您的帮助!
终于排版成功了!
使用的方法是<include />
另一个布局作为这个布局中的行元素。所有这些行元素都具有相同的数据,因此每当视图发生变化时,我都会以编程方式用必要的数据填充行元素。您也可以将其作为 ListView 执行此操作,ListView 中的每一行都是另一对元素,但我不确定这对 4 元素宽行的效果如何。
每一行的XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/statNameString"
android:id="@+id/statName"
android:layout_marginTop="30dp"
android:gravity="center" />
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_height="match_parent"
android:background="#663300"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/statValString"
android:id="@+id/statVal"
android:layout_marginTop="30dp"
android:gravity="center" />
</LinearLayout>
顶行(代表我应用中角色的 Class)需要包含一个 ImageView,因此它的布局略有变化。 ImageView 放置在条形视图之后,最后一个 TextView 之前。
将XML每一行都包含到最终布局中,对于Land布局:
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/horizontal_class_row_layout"
android:id="@+id/strValues"
android:layout_column="0" />
<include
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/horizontal_class_row_layout"
android:id="@+id/intValues"
android:layout_column="0" />
</TableRow>
如果您只想在每行中放置一对元素,您只需删除其中一个包含标签即可。如前所述,您也可以使用 ListView 来执行这些操作,并填充数据,我可能最终会对其进行修改。
最后,您以编程方式在 Java 中用它们的数据填充元素,因此它们不只是说 "Class" 和 "Class Value" 或任何默认数据:
private void fillViewValues() {
//Gather views
LinearLayout llClass = (LinearLayout)findViewById(R.id.classValues);
LinearLayout llStr = (LinearLayout)findViewById(R.id.strValues);
LinearLayout llDex = (LinearLayout)findViewById(R.id.dexValues);
LinearLayout llCon = (LinearLayout)findViewById(R.id.conValues);
LinearLayout llInt = (LinearLayout)findViewById(R.id.intValues);
LinearLayout llWis = (LinearLayout)findViewById(R.id.wisValues);
LinearLayout llCha = (LinearLayout)findViewById(R.id.chaValues);
//Get the layout's locations
TextView classNameView = (TextView) llClass.findViewById(R.id.statName);
TextView classValView = (TextView) llClass.findViewById(R.id.statVal);
ImageView classImage = (ImageView) llClass.findViewById(R.id.classicon);
TextView strNameView = (TextView) llStr.findViewById(R.id.statName);
TextView strValView = (TextView) llStr.findViewById(R.id.statVal);
TextView dexNameView = (TextView) llDex.findViewById(R.id.statName);
TextView dexValView = (TextView) llDex.findViewById(R.id.statVal);
TextView conNameView = (TextView) llCon.findViewById(R.id.statName);
TextView conValView = (TextView) llCon.findViewById(R.id.statVal);
TextView intNameView = (TextView) llInt.findViewById(R.id.statName);
TextView intValView = (TextView) llInt.findViewById(R.id.statVal);
TextView wisNameView = (TextView) llWis.findViewById(R.id.statName);
TextView wisValView = (TextView) llWis.findViewById(R.id.statVal);
TextView chaNameView = (TextView) llCha.findViewById(R.id.statName);
TextView chaValView = (TextView) llCha.findViewById(R.id.statVal);
//Fill those values
//Names of sections
classNameView.setText(getResources().getString(R.string.classString));
strNameView.setText(getResources().getString(R.string.strString));
dexNameView.setText(getResources().getString(R.string.dexString));
conNameView.setText(getResources().getString(R.string.conString));
intNameView.setText(getResources().getString(R.string.intString));
wisNameView.setText(getResources().getString(R.string.wisString));
chaNameView.setText(getResources().getString(R.string.chaString));
//Values
classValView.setText(classString);
setImage(classImage, classString);
strValView.setText(String.format("%d", finalStats[0]));
dexValView.setText(String.format("%d", finalStats[1]));
conValView.setText(String.format("%d", finalStats[2]));
intValView.setText(String.format("%d", finalStats[3]));
wisValView.setText(String.format("%d", finalStats[4]));
chaValView.setText(String.format("%d", finalStats[5]));
}
这遵循 at this Whosebug post.
的建议
我要注意的一件事是,当您更改布局时,您需要将内容视图重置为当前布局。在我的例子中,函数看起来像:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
setContentView(R.layout.activity_see_character);
fillViewValues();
}else if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
setContentView(R.layout.activity_see_character);
fillViewValues();
}
}
其中 fillViewValues() 是前一个函数。我相信这会将布局设置为布局的纵向或横向版本,然后可以访问其元素。如果您在尝试访问元素时不这样做,它将找不到它们并给出 NullPointerException。
我的应用程序上的一个页面有一个 table 布局页面,其中一行似乎不起作用。我的目标是在左侧单元格和右侧单元格之间平均拆分页面。左侧单元格包含一个字符串,右侧单元格包含一个图像和字符串。我尝试使用 weightSum 这样做。左侧单元格的权重为 4/8,右侧单元格为线性布局,其中图像的权重为 1/8,字符串的权重为 3/8。但是,在布局中,左侧单元格占据了行的绝大部分,大约 75%,我不确定为什么。
我下面这一行尝试了几乎相同的事情,但没有同样的问题。
我的 xml(因相关性而删减):
<TableRow
android:layout_width="match_parent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Class"
android:id="@+id/classTextView"
android:layout_marginTop="14dp"
android:layout_weight="1"
android:gravity="center"/>
<LinearLayout>
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_height="match_parent"
android:background="#663300"/>
<ImageView
tools:ignore="ContentDescription"
android:id="@+id/classicon"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/barbarianicon50"
android:layout_gravity="end"
android:layout_weight="1"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Class Value"
android:id="@+id/classValueView"
android:layout_marginTop="14dp"
android:layout_weight="3"
android:gravity="left"/>
</LinearLayout>
</TableRow>
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="#663300"/>
<TableRow android:layout_width="match_parent">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Strength"
android:id="@+id/strengthTextView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
<LinearLayout>
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_weight="0"
android:layout_height="match_parent"
android:background="#663300"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Strength Value"
android:id="@+id/strengthValView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Intelligence"
android:id="@+id/intelligenceTextView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
<LinearLayout>
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_weight="0"
android:layout_height="match_parent"
android:background="#663300"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Intelligence Value"
android:id="@+id/intelligenceValView"
android:layout_marginTop="20dp"
android:layout_weight="4"
android:gravity="center" />
</LinearLayout>
</TableRow>
第一 table 行是有问题的行 - 它应该在左右单元格之间平均分配,但大部分偏向右侧。
第二个 table 行是它正常工作的一个例子 - 这一行有 2 对单元格,但是每个单元格,以及每对单元格都正确地平均分配了它们之间的宽度。
我不明白为什么第一个不起作用。感谢您的帮助!
终于排版成功了!
使用的方法是<include />
另一个布局作为这个布局中的行元素。所有这些行元素都具有相同的数据,因此每当视图发生变化时,我都会以编程方式用必要的数据填充行元素。您也可以将其作为 ListView 执行此操作,ListView 中的每一行都是另一对元素,但我不确定这对 4 元素宽行的效果如何。
每一行的XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2">
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/statNameString"
android:id="@+id/statName"
android:layout_marginTop="30dp"
android:gravity="center" />
<View
android:layout_width="4dp"
android:gravity="left"
android:layout_height="match_parent"
android:background="#663300"/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/statValString"
android:id="@+id/statVal"
android:layout_marginTop="30dp"
android:gravity="center" />
</LinearLayout>
顶行(代表我应用中角色的 Class)需要包含一个 ImageView,因此它的布局略有变化。 ImageView 放置在条形视图之后,最后一个 TextView 之前。
将XML每一行都包含到最终布局中,对于Land布局:
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/horizontal_class_row_layout"
android:id="@+id/strValues"
android:layout_column="0" />
<include
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
layout="@layout/horizontal_class_row_layout"
android:id="@+id/intValues"
android:layout_column="0" />
</TableRow>
如果您只想在每行中放置一对元素,您只需删除其中一个包含标签即可。如前所述,您也可以使用 ListView 来执行这些操作,并填充数据,我可能最终会对其进行修改。
最后,您以编程方式在 Java 中用它们的数据填充元素,因此它们不只是说 "Class" 和 "Class Value" 或任何默认数据:
private void fillViewValues() {
//Gather views
LinearLayout llClass = (LinearLayout)findViewById(R.id.classValues);
LinearLayout llStr = (LinearLayout)findViewById(R.id.strValues);
LinearLayout llDex = (LinearLayout)findViewById(R.id.dexValues);
LinearLayout llCon = (LinearLayout)findViewById(R.id.conValues);
LinearLayout llInt = (LinearLayout)findViewById(R.id.intValues);
LinearLayout llWis = (LinearLayout)findViewById(R.id.wisValues);
LinearLayout llCha = (LinearLayout)findViewById(R.id.chaValues);
//Get the layout's locations
TextView classNameView = (TextView) llClass.findViewById(R.id.statName);
TextView classValView = (TextView) llClass.findViewById(R.id.statVal);
ImageView classImage = (ImageView) llClass.findViewById(R.id.classicon);
TextView strNameView = (TextView) llStr.findViewById(R.id.statName);
TextView strValView = (TextView) llStr.findViewById(R.id.statVal);
TextView dexNameView = (TextView) llDex.findViewById(R.id.statName);
TextView dexValView = (TextView) llDex.findViewById(R.id.statVal);
TextView conNameView = (TextView) llCon.findViewById(R.id.statName);
TextView conValView = (TextView) llCon.findViewById(R.id.statVal);
TextView intNameView = (TextView) llInt.findViewById(R.id.statName);
TextView intValView = (TextView) llInt.findViewById(R.id.statVal);
TextView wisNameView = (TextView) llWis.findViewById(R.id.statName);
TextView wisValView = (TextView) llWis.findViewById(R.id.statVal);
TextView chaNameView = (TextView) llCha.findViewById(R.id.statName);
TextView chaValView = (TextView) llCha.findViewById(R.id.statVal);
//Fill those values
//Names of sections
classNameView.setText(getResources().getString(R.string.classString));
strNameView.setText(getResources().getString(R.string.strString));
dexNameView.setText(getResources().getString(R.string.dexString));
conNameView.setText(getResources().getString(R.string.conString));
intNameView.setText(getResources().getString(R.string.intString));
wisNameView.setText(getResources().getString(R.string.wisString));
chaNameView.setText(getResources().getString(R.string.chaString));
//Values
classValView.setText(classString);
setImage(classImage, classString);
strValView.setText(String.format("%d", finalStats[0]));
dexValView.setText(String.format("%d", finalStats[1]));
conValView.setText(String.format("%d", finalStats[2]));
intValView.setText(String.format("%d", finalStats[3]));
wisValView.setText(String.format("%d", finalStats[4]));
chaValView.setText(String.format("%d", finalStats[5]));
}
这遵循 at this Whosebug post.
的建议我要注意的一件事是,当您更改布局时,您需要将内容视图重置为当前布局。在我的例子中,函数看起来像:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
{
setContentView(R.layout.activity_see_character);
fillViewValues();
}else if(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
{
setContentView(R.layout.activity_see_character);
fillViewValues();
}
}
其中 fillViewValues() 是前一个函数。我相信这会将布局设置为布局的纵向或横向版本,然后可以访问其元素。如果您在尝试访问元素时不这样做,它将找不到它们并给出 NullPointerException。