【问题标题】:Android LinearLayout is not redisplayed after changing weights programmatically以编程方式更改权重后不会重新显示 Android LinearLayout
【发布时间】:2015-06-09 19:06:59
【问题描述】:

我能够以编程方式构造一个包含数十个视图的 LinearLayout,并将其显示为 Activity 的内容视图。我能够遍历 LinearLayout 树并更改视图的背景颜色。

我可以在树中行走并调整视图的相对权重,并在 onCreate() 结束时调用 setContentView() 来显示树。

我有一个 seekBar 以交互方式调整颜色,这很有效。同样,我有一个 seekBar 以交互方式调整权重。我知道权重正在正确更改。

但不知何故,在交互式更改权重后视图不会重新显示,而在交互式更改颜色后会重新显示。

更改权重后,我必须做什么才能重新显示内容视图?

【问题讨论】:

  • 您应该向我们展示您的代码。你试过 invalidate() 吗?
  • requestLayout() 在更改的视图或父视图上
  • 嗯,这是一个简单的问题,所以现在我认为发布代码会让我们陷入困境。我可以在调用 setContentView() 之前以编程方式更改权重,一切都很好。但交互地,内容视图不会重绘。显示器中的颜色会根据需要交互变化。根据您的建议,我在内容视图上尝试了 invalidate() ,但这似乎没有任何效果。
  • requestLayout() 似乎也没有帮助。运行它或 invalidate() 有什么技巧吗?我只是在整个内容视图树上调用它们,没有任何变化。
  • 很难说发生了什么。没有看到任何代码,我们都只是猜测。

标签: android android-linearlayout android-layout-weight setcontentview


【解决方案1】:

requestLayout() 为我工作

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical">
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/seek"
        android:progress="50"
        android:max="100"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:id="@+id/linear">
        <View
            android:layout_width="0dp"
            android:layout_height="20dp"
            android:layout_weight="1"
            android:id="@+id/blue"
            android:background="#00f"/>
        <View
            android:layout_width="0dp"
            android:layout_height="20dp"
            android:layout_weight="1"
            android:id="@+id/red"
            android:background="#f00"/>
    </LinearLayout>
</LinearLayout>

public class MainActivity extends AppCompatActivity {
    private LinearLayout linear;
    private View red;
    private View blue;

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

        SeekBar seek = (SeekBar) findViewById(R.id.seek);
        linear = (LinearLayout) findViewById(R.id.linear);
        red = findViewById(R.id.red);
        blue = findViewById(R.id.blue);
        seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                ((LinearLayout.LayoutParams) red.getLayoutParams()).weight = 100 - progress;
                ((LinearLayout.LayoutParams) blue.getLayoutParams()).weight = progress;

                linear.requestLayout();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }
}

【讨论】:

  • 我刚刚实现了与您上面的代码非常相似的东西。然而,除了交互式调整宽度之外,我的以编程方式构建整个布局。如果有人感兴趣,我可以发布我的代码。正如您所建议的,使用 requestLayout() 会有所不同。所以在某种意义上回答了我的问题,谢谢。我一定有其他错误。调用 invalidate() 没有任何明显的效果。但是我一直在构建的程序的布局具有更复杂的树结构。如果我找到它,或者如果我找到任何有希望的线索,我会返回一个完整的答案。
【解决方案2】:

我找到了一个答案,为什么即使调用 requestLayout() 权重也不会改变。我制作了一个类似于 karokyo 的程序,但我的不使用 XML 布局文件。就像上面的 karakyo 一样,它使用 seekBar 交互地改变权重。但它以编程方式创建所有视图。我发现在将视图添加到 ViewGroup(例如,LinearLayout)时,提供给 addView() 的 LayoutParams 不会复制到视图中,而是作为对象添加。因此,如果在多个 addView() 调用中提供了一个 LayoutParams,那么添加的视图将共享相同的 LayoutParams。然后,如果一个 View 的权重发生变化(通过分配给 getLayoutParams()).weight),其他 View 的权重也会发生变化,因为它们共享相同的 LayoutParams 对象。显然,当从 XML 布局中扩展视图时,每个视图都有自己的 LayoutParams 对象。

package course.example.interactiveweightexperiment;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;


public class WeightSeekBar extends Activity {
    private final String TAG = "WeightSeekBar-TAG";
    private LinearLayout mainLayout;
    private LinearLayout linearColors;
    private View redView;
    private View blueView;
    SeekBar weightSeekBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        redView = new View(this);
        redView.setBackgroundColor(0xff770000);

        blueView = new View(this);
        blueView.setBackgroundColor(0xff000077);

        weightSeekBar = new SeekBar(this);
        weightSeekBar.setMax(100);
        weightSeekBar.setProgress(50);

        weightSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                ((LinearLayout.LayoutParams) redView.getLayoutParams()).weight = 100 - progress;
                ((LinearLayout.LayoutParams) blueView.getLayoutParams()).weight = progress;

                linearColors.requestLayout();
                // linearColors.invalidate();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        linearColors = new LinearLayout(this);
        linearColors.setOrientation(LinearLayout.VERTICAL);

        linearColors.addView(redView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 50));
        linearColors.addView(blueView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 50));

        /* the following does not allow the child Views to be assigned different weights.
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 50);
        linearColors.addView(redView, params);
        linearColors.addView(blueView, params);
        */

        mainLayout = new LinearLayout(this);
        mainLayout.setOrientation(LinearLayout.VERTICAL);
        mainLayout.addView(linearColors, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 19));
        mainLayout.addView(weightSeekBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1));

        setContentView(mainLayout);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    • 2013-08-23
    相关资源
    最近更新 更多