【问题标题】:Layout a view after resizing调整大小后布局视图
【发布时间】:2012-10-13 12:21:08
【问题描述】:

我正在创建一个显示经常变化的值的网格。因此,我使用了一个 TextView,它会在其内容更改时自动调整大小 (Auto Scale TextView Text to Fit within Bounds)。调整大小发生,但视图布局不正确

问题是,当我使用 HierarchyViewer 检查活动时,布局显示为我想要的。

我的猜测是 HierarchyViewer 在视图上调用 requestLayout() 或 invalidate(),但我尝试过没有成功。这段代码在主活动中被调用,没有任何效果。

new Handler().postDelayed(new Runnable() {            
            @Override
            public void run() {
              getWindow().getDecorView().requestLayout();
              getWindow().getDecorView().invalidate();
            }
          }, 5000);

我也尝试在调整大小后使视图无效。

TextView 的重力设置为Center,如果没有调整大小,它看起来没问题。

欢迎任何提示,提前谢谢!

【问题讨论】:

  • 您是否尝试过请求父视图而不是装饰视图的布局?
  • 装饰视图不是View树的父节点吗?我读到请求视图上的布局会导致其所有子级请求布局。无论如何,我会说我已经尝试过,因为我已经尝试了很多东西,但是当我尝试你的建议时我会报告。引用 view.View 上的 requestLayout 文档,“当某些事情发生变化时调用这个,这使得该视图的布局无效。这将安排视图树的布局传递。”
  • 确实如此,但我看不出您的代码有什么问题。 requestLayout() 布局一个父视图和它的子视图,但我只在我的应用程序直接控制的视图上调用它,所以这只是一个想法。
  • 已修复!我必须使用处理程序在其中一个视图父级上调用 requestLayout。我不知道为什么它在使用装饰视图时不起作用,我在 UI 线程上调用它,但我还是很高兴 :D 因为我必须给予赏金,请回答问题
  • 看起来你已经想通了,所以我会让你保留赏金(假设你在自己的问题上接受赏金时会发生这种情况)。

标签: android hierarchyviewer


【解决方案1】:

我通过覆盖 TextView 的父级之一中的 onLayout 并使用在构造函数中创建的处理程序解决了这个问题

public class CellView extends LinearLayout{
   public CellView(Context context) {
     super(context);

     mHandler = new Handler();

     View.inflate(context, R.layout.cellview, this);
  }

 @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    if(changed){
      mHandler.post(new Runnable() {          
        @Override
        public void run() {
          requestLayout();
        }
      });
    }

   super.onLayout(changed, left, top, right, bottom);
  }

我曾尝试在 TextView 的 onLayout 中调用 requestLayout,但它不起作用,我不知道为什么。这可能是因为值是通过观察者更新的,但 onTextChanged 侦听器应该发生在 UI 线程中。我希望它服务于其他人

【讨论】:

    【解决方案2】:

    requestLayout() 的工作方式是,当在视图上调用时,它将在其自身及其所有子级上安排布局传递。每当视图对边距、填充或内容更改进行了移动或调整大小时,这都是可取的。

    getDecorView() 方法的文档并不清楚它到底给了你什么。但是,根据website 上的文档:

    请注意,第一次调用此函数会“锁定”各种窗口特征,如 setContentView(View, android.view.ViewGroup.LayoutParams) 中所述。

    这让我相信getDecorView() 检索到的视图有一些特别之处。您可能正在做的是使视图的布局永久化,因此当您通过requestLayout() 传递时永远不会改变。

    This is apparently the proper way to get the root view of your entire activity.

    但是,出于效率原因,我建议您尽可能对最低的孩子调用requestLayout()。就像我之前说的,它在一个视图和它的子视图上安排一个布局传递。如果您在最顶层的视图上进行布局传递,那么您实质上是在重建包括保留在原地的视图在内的所有内容。

    【讨论】:

    • 你来了,感谢您的时间和对 requestLayout 的出色研究,但我会保留我的选择答案,因为它解决了我的具体问题。如果以后有用户投票给你,我会奖励给你
    【解决方案3】:

    您可能需要使用 runOnUiThread 在 UI 线程中运行计时器代码,如 here 所述。

    【讨论】:

    • 假设他在UI线程中创建Handler,它是在UI线程中运行的。
    • 我稍后会检查这个(现在不处理这个)。我会说从 UI 线程外部运行该代码会导致异常,但我可能会在 UI 线程外部创建处理程序。感谢(Narcís 和 DeeV)的想法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    • 2011-01-03
    • 2021-03-11
    相关资源
    最近更新 更多