Android:以编程方式填充线性布局,得到额外的 space

Android: populating Linear Layout programmatically, It gets extra space

我正在尝试以编程方式用一些 ImageViews 水平填充 LinearLayout。在水平方向上,一切都很好,但它在垂直方向上保留了额外的 space 我不想要的东西。

这里是 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="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="es.uam.dadm.jacopo_grassi_connecta4.Settings" >

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/your_color" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:id="@+id/your_color_container" >

</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/adv_color" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:id="@+id/adv_color_container" >

</LinearLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/sounds" />

    <Switch
        android:id="@+id/sounds_switch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true" />
</RelativeLayout>

这里是 java 代码:

private PlayerDataSource playersdb;
private Player player;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_settings);

    Bundle extras = getIntent().getExtras();
    playersdb = new PlayerDataSource(this);
    player = playersdb.getPlayer(extras.getString(Utils.PARAM_PLAYER_ID));

    buildColors();

    Switch sounds = (Switch)findViewById(R.id.sounds_switch);
    sounds.setOnCheckedChangeListener(this);
    sounds.setChecked(player.getSounds() == 0 ? false : true);
}

@Override
public void onClick(View v) {
    Integer tag = (Integer) v.getTag(R.id.TAG_ADV);
    if(tag == null){        //your color
        tag = (Integer) v.getTag(R.id.TAG_YOU);
        player.setColor(tag);
    }else{                  //adv color
        player.setColorAdv(tag);
    }
    playersdb.updatePlayer(player);
    buildColors();
}

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    if(isChecked){
        player.setSounds(1);
    }else{
        player.setSounds(0);
    }
    playersdb.updatePlayer(player);
}

private void buildColors(){
    LinearLayout parent = (LinearLayout)findViewById(R.id.your_color_container);
    parent.removeAllViewsInLayout();

    for (int i = 0; i < 5; ++i) {
        LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        params.weight = 0.2f;
        ImageView v = new ImageView(this);
        Integer drawable = null;
        switch (i){
        case 0:
            drawable = R.drawable.red_piece;
            break;
        case 1:
            drawable = R.drawable.yellow_piece;
            break;
        case 2:
            drawable = R.drawable.green_piece;
            break;
        case 3:
            drawable = R.drawable.purple_piece;
            break;
        case 4:
            drawable = R.drawable.azure_piece;
            break;
        }
        v.setLayoutParams(params);
        v.setImageResource(drawable);
        v.setTag(R.id.TAG_YOU, drawable);
        v.setOnClickListener(this);

        if (drawable.equals(player.getColor())) {
            v.setBackgroundColor(getResources().getColor(R.color.azul));
        }

        parent.addView(v);
    }

    parent = (LinearLayout)findViewById(R.id.adv_color_container);
    parent.removeAllViewsInLayout();

    for (int i = 0; i < 5; ++i) {
        LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        params.weight = 0.2f;
        ImageView v = new ImageView(this);
        Integer drawable = null;
        switch (i){
        case 0:
            drawable = R.drawable.red_piece;
            break;
        case 1:
            drawable = R.drawable.yellow_piece;
            break;
        case 2:
            drawable = R.drawable.green_piece;
            break;
        case 3:
            drawable = R.drawable.purple_piece;
            break;
        case 4:
            drawable = R.drawable.azure_piece;
            break;
        }
        v.setLayoutParams(params);
        v.setImageResource(drawable);
        v.setTag(R.id.TAG_ADV, drawable);
        v.setOnClickListener(this);

        if (drawable.equals(player.getColorAdv())) {
            v.setBackgroundColor(getResources().getColor(R.color.azul));
        }

        parent.addView(v);
    }
}

这就是结果:

显然,图像是完美的正方形。

我做错了什么?

如果将 outer LinearLayout 的 android:layout_height 更改为 "wrap_content" 是否有效?

尝试将 LinearLayout.Params 宽度和高度设为 "LayoutParams.WRAP_CONTENT" 以及 XML 文件中线性布局的高度

尝试parent.addView(v, params);

这就是解决您问题的方法。

(以下代码应在 parent.addView(v)

之前添加到您的 for 循环中

您需要使用 Runnable 线程才能获得将在运行时设置为高度的视图宽度,否则您将在知道视图宽度之前尝试设置高度,因为布局还没有还没抽到。

v.post(new Runnable() {
    @Override
    public void run() {
        LinearLayout.LayoutParams mParams;
        mParams = (LinearLayout.LayoutParams) v.getLayoutParams();
        mParams.height = v.getWidth();
        v.setLayoutParams(mParams);
        v.postInvalidate();
    }
});

v.postInvalidate() 被调用以强制视图在与 UI 线程

不同的线程上重绘

感谢@Terence 解决了 已添加

v.setAdjustViewBounds = true;