【问题标题】:How to force an entire layout View refresh?如何强制整个布局视图刷新?
【发布时间】:2011-08-24 22:04:05
【问题描述】:

我想强制主布局资源视图重绘/刷新,比如 Activity.onResume() 方法。我怎样才能做到这一点 ?

主布局视图是指在我的 Activity.onCreate() 中调用的那个(下面的“R.layout.mainscreen”),如下所示:-

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainscreen);
}

【问题讨论】:

  • 您是否尝试过命名您的封闭式 Linear/Relative/WhateverLayout,对其调用 findViewById,然后对其调用 invalidate()? (我会将此作为答案,但我不知道使父母无效是否也会使孩子无效,而且我无法测试它。)
  • 也谢谢!不过,我仍在为此苦苦挣扎。你可以看看我在下面发布的内容。我需要这段代码(或其他?)来刷新我的主题...

标签: android layout refresh


【解决方案1】:

严格回答问题:使用invalidate():

公共无效无效() 自:API 级别 1

使整个视图无效。如果视图可见,onDraw(Canvas) 将在将来的某个时间点被调用。这必须从 UI 线程调用。要从非 UI 线程调用,请调用 postInvalidate()。

ViewGroup vg = findViewById (R.id.mainLayout);
vg.invalidate();

现在,当 Activity 恢复时,它会让每个 View 都绘制自己。不需要调用 invalidate()。要应用主题,请确保在绘制任何视图之前执行此操作,即在 setContentView(R.layout.mainscreen);

之前

public void setTheme (int resid) 自:API 级别 1

为此上下文设置基本主题。请注意,这应该在上下文中实例化任何视图之前调用(例如,在调用 setContentView(View) 或 inflate(int, ViewGroup) 之前)。

API 文档参考在这里:http://developer.android.com/reference/android/view/ContextThemeWrapper.html#setTheme%28int%29

由于 onDraw() 方法适用于已经实例化的视图,因此 setTheme 将不起作用。我自己对主题没有经验,但我能想到的两个替代选择是:

  1. 改为在 onCreate() 中调用 setTheme,或者
  2. 重做 setContentView (R.layout.mainscreen);强制重新实例化所有布局。

【讨论】:

  • 谢谢!这运行正常,但我没有看到我的预期。就在运行您的代码之前,我运行了 Activity.setTheme(newtheme) 但这个 invalidate() 调用不会导致主题发生变化(例如从暗到亮)。 invalidate() 应该能够做到这一点吗?
  • @MickeyR 不,不应该。检查我更新的答案。如果这两个选项不起作用,您将需要重新启动 Activity。
  • 选项 (1) 确实有效。我的应用程序将以正确的主题启动,但如果我在运行时更改它,我必须重新启动我的应用程序以便再次调用 onCreate()。
  • 选项(2)是我想走的路线。因此,当运行时更改主题时,我希望 onRestart() 这样做:- setTheme(getPreferenceTheme());和 setContentView(R.layout.main);但这不会改变我的主题。我无法让第二个选项起作用...?!
  • 我知道要让选项 (2) 正常工作,我需要“重新扩展视图层次结构”。我尝试了不同的方法来实现这一点,但我不确定这意味着什么,也不知道如何做到这一点。
【解决方案2】:

试试getWindow().getDecorView().findViewById(android.R.id.content).invalidate();

【讨论】:

  • 谢谢!我在上面发布给 Aleadam 的答案相同。这个 invalidate() 不会导致活动主题刷新,这是我需要的。
【解决方案3】:

尝试recreate(),它将导致重新创建此活动。

【讨论】:

  • 我尝试了这个线程中的所有选项,这是唯一一个副作用最少的选项。
  • 如果我需要在onResume 方法中执行此操作。这给了我无限循环:/
  • 好吧,除非你真的需要,否则我不建议使用它。您可以在共享首选项中保存一些标志以避免无限循环。
  • 这可行,但我不建议在真正的生产模式应用程序中使用它。我只需要它用于调试模式,因此整个 UI 刷新的副作用并不重要。
【解决方案4】:

解决方案:

伙计们,我尝试了你所有的解决方案,但它们对我没有用,我必须将 EditText 的 setVisibility 设置为 VISIBLE,然后这个 EditText 应该在 ScrollView,但无法刷新根视图生效。 我解决了我的问题,当我需要刷新视图时,我将 ScrollView 可见性更改为 GONE,然后再次将其设置为 VISIBLE 以生效,它对我有用。这不是确切的解决方案,但它只是有效。

 private void refreshView(){
    mScrollView.setVisibility(View.GONE);
    mScrollView.setVisibility(View.VISIBLE);
}

【讨论】:

  • 哇..我也尝试了所有建议的解决方案,但这似乎是唯一可行的解​​决方案,但这有点可怕......
  • @NaveedAhmad 谢谢!经过 4 小时的努力,这是唯一有效的解决方案。
  • 此解决方案有效,因为设置可见性会调用requestLayout() on view。见docs
【解决方案5】:

在根布局上调用invalidate()postInvalidate() 显然不能保证子视图会被重绘。在我的具体情况下,我的根布局是一个 TableLayout,并且有几个 TableRow 和 TextView 类的子级。在根 TableLayout 对象上调用 postInvalidate()requestLayout() 甚至 forceLayout() 不会导致布局中的任何 TextView 被重绘。

所以,我最终做的是递归解析布局以查找那些 TextView,然后在每个 TextView 对象上调用 postInvalidate()

代码可以在 GitHub 上找到: https://github.com/jkincali/Android-LinearLayout-Parser

【讨论】:

    【解决方案6】:

    否则你也可以试试这个-

    ViewGroup vg = (ViewGroup) findViewById (R.id.videoTitleTxtView);
     vg.removeAllViews();
     vg.refreshDrawableState();
    

    【讨论】:

    • 谢谢!但是,这删除了我拥有的所有视图(TextView、按钮等)但没有重新绘制它们 - 我的屏幕仍然是空白的......
    • 你需要刷新你的视图,然后你需要再次调用draw函数。清理上一个视图后。
    【解决方案7】:

    只需在 onresume 中设置您的内容视图

    setContentView(R.layout.yourview) 里面 onResume..

    例子:

    @Override
    public void onResume(){
    super.onResume();
    setContentView(R.layout.activity_main); 
    postIncomeTotals();
    }
    

    【讨论】:

    • 嗨,我试过这个,listview 中的相同数据被拉了两次,因此如果我有 4 行并且刷新应该添加第五行,而不是我最终得到 10,然后是 15,。 ..怎么办?
    【解决方案8】:

    试试这个解决主题问题的方法:

    @Override
    public void onBackPressed() {
        NavUtils.navigateUpTo(this, new Intent(this,
                MyNeedToBeRefreshed.class));
    }
    

    【讨论】:

      【解决方案9】:
      Intent intent = getIntent();
      intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
      finish();
      startActivity(intent);
      

      这允许您重新加载主题更改并隐藏动画。

      【讨论】:

        【解决方案10】:

        我也遇到了这个问题,但是按照 Farhan 使用setContentView() 的方法,我做到了。然而,单独使用setContentView() 是不够的。我发现我必须用信息重新填充我的所有视图。为了解决这个问题,我只是将所有这些代码提取到另一个方法中(我称之为 build),在我的 onCreate 方法中我只是调用那个 build。现在,每当我希望我的活动“刷新”的事件发生时,我只需调用 build,给它新信息(我将其作为参数传递给 build),然后我就有了一个刷新的活动。

        【讨论】:

          【解决方案11】:

          这似乎是known bug

          【讨论】:

          • setTheme 可以在我重新启动活动时找到(调用完成(),然后调用 startActivity())。我只是无法在不重新启动我的活动的情况下刷新主题...
          【解决方案12】:

          试试这个

          view.requestLayout();
          

          【讨论】:

            【解决方案13】:

            我不知道这是否安全,但它对我有用。我自己也遇到了这个问题并尝试了invalidate()requestLayout() 但无济于事。所以我再次打电话给我的onCreate(null),它成功了。如果这不安全,请告诉我。希望这对那里的人有所帮助。

            【讨论】:

            【解决方案14】:

            这就是我过去刷新布局的方式

            Intent intent = getIntent();
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
            finish();
            startActivity(intent);
            

            【讨论】:

              【解决方案15】:

              要清除扩展 ViewGroup 的视图,只需要使用方法removeAllViews()

              就像这样(如果您有一个名为 myElement 的 ViewGroup):

              myElement.removeAllViews()
              

              【讨论】:

                【解决方案16】:

                如果您要创建自定义视图,请确保它扩展了 SurfaceView,然后您可以使用方法 getHolder().lockCanvas() 重新绘制它。这是一个例子:

                Canvas c = getHolder().lockCanvas();
                c.drawText("Text", x, y, paint);
                getHolder().unlockCanvasAndPost(c);
                

                【讨论】:

                  【解决方案17】:

                  不确定这是否是好方法,但我每次都调用它:

                  setContentView(R.layout.mainscreen);
                  

                  【讨论】:

                    【解决方案18】:

                    只需使用意图再次调用活动本身。 例如刷新 MainActivity 的布局,这样做:

                    startActivity(new Intent(MainActivity.this, MainActivity.class));
                    

                    【讨论】:

                    • 太丑了!当你这样做时,你只需在堆栈上添加一个新的活动,所以,当你按下后退按钮时,你会回到同一个活动。
                    猜你喜欢
                    • 1970-01-01
                    • 2022-12-07
                    • 2013-08-30
                    • 1970-01-01
                    • 2013-04-24
                    • 2014-11-13
                    • 2020-09-09
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多