【问题标题】:How to set layout dynamically in android如何在android中动态设置布局
【发布时间】:2013-06-08 20:00:48
【问题描述】:

好吧,假设有一个名为 MainActivity 的 Activity,并且有两个名为 layout1layout2 的布局,它们的按钮很少。默认情况下,MainActivity 布局为 layout1,如下所示:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout1);

现在我实际上是通过单击 layout1 中的一个按钮来设置第二个布局,如下所示:

    someBtn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            setContentView(R.layout.layout2);
        }
    });

layout2 中有另一个按钮可以返回 layout1,如下所示:

    someBtn2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            setContentView(R.layout.layout1);
        }
    });

问题是当我返回 layout1 时,someBtn1 的 OnClickListener 不起作用。看来我需要再次为 layout1someBtn1 设置 OnClickListener。 我如何编写代码以使它们与最佳实践完美结合?

【问题讨论】:

    标签: java android android-layout android-intent


    【解决方案1】:

    如果你只是想玩弄你当前的代码,解决你的问题的方法是当布局改变时必须重新声明监听器,如下:

    someBtn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            setContentView(R.layout.layout2);
    
            someBtn2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    setContentView(R.layout.layout1);
                }
            });
        }
    });
    
    someBtn2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            setContentView(R.layout.layout1);
    
            someBtn1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    setContentView(R.layout.layout2);
                }
            });
        }
    });
    

    避免两次声明侦听器的另一种方法是声明两个方法来处理布局更改并在每个布局中使用按钮的onClick 属性,例如:

    public void setLayout1(View view) {
        setContentView(R.layout.layout1);
    }
    
    public void setLayout2(View view) {
        setContentView(R.layout.layout2);
    }
    

    layout1.xml:

    <Button
        android:id="@+id/someBtn1"
        android:onClick="setLayout2"/>
    

    layout2.xml:

    <Button
        android:id="@+id/someBtn2"
        android:onClick="setLayout1"/>
    

    但是,如果您想遵循最佳实践,最佳实践不是在同一个活动中混合布局,而是声明两个不同的活动(每个活动都有自己的布局)并根据具体情况调用一个活动或另一个活动。被点击的按钮。假设你在Activity1,想调用Activity2,然后回到Activity1:

    Activity1.java:

    someBtn1.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             startActivity(new Intent(this, Activity2.class));
         }
     });
    

    Activity2.java:

    someBtn2.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             finish();
         }
     });
    

    【讨论】:

    • 是的,我知道。但出于某种原因,我想在同一活动中动态使用不同的布局。感谢您的建议。
    • 我已经改进了我的答案以避免两次声明听众,请看一下。
    【解决方案2】:

    在你回调layout1的时候,必须重新设置数据。

    您可以将两种布局合并为一个,然后使用 ViewFlipper 在它们之间切换。

    【讨论】:

      【解决方案3】:

      这样做的一种方法是在onCreate(...) 中加载两个视图,然后通过使您不希望的视图不可见来在它们之间切换。类似于以下内容:

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          LayoutParams default_layout_params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
          View view1 = inflater.inflate(R.layout.layout1, null);
          addContentView(view1, default_layout_params);           
          View view2 = inflater.inflate(R.layout.layout2, null);
          addContentView(view2, default_layout_params);
          view2.setVisibility(View.INVISIBLE);
          view1.setVisibility(View.VISIBLE);
          view1.bringToFront();
      

      【讨论】:

      • 感谢您的代码。实际上,我需要在一项活动中切换 3-4 个布局。这就是为什么我仍然混淆我应该使用什么。在这种情况下使用 Fragment 会更好吗?
      • 我刚刚发布了已成功用于两种布局的代码。我很确定这种方法会更有效,但betterbest 是主观的,所以我将选择权留给你!
      【解决方案4】:

      当您设置 layout2 时,您还应该将 OnClickListener 设置为 someBtn1,反之亦然,我建议您这样做。但就像之前的回答一样,一般来说,您应该避免以这种方式混合布局。

      public class MainActivity extends Activity {
      
          private final View.OnClickListener setLayout1Listener = new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                 setContentView(R.layout.layout2);
                 ((Button)findViewById(R.id.Btn2Id)).setOnClickListener(setLayout2Listener);
                 //do other stuff
              }
          };
      
          private final View.OnClickListener setLayout2Listener = new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                 setContentView(R.layout.layout1);
                 ((Button)findViewById(R.id.Btn1Id)).setOnClickListener(setLayout1Listener);
                 //do other stuff
              }
          };
      
      
      
          @Override
          public void onCreate(final Bundle savedInstance) {
      
              super.onCreate(savedInstanceState);
              setContentView(R.layout.layout1);
              ((Button)findViewById(R.id.Btn1Id)).setOnClickListener(setLayout1Listener);
              //do other stuff
          }
      }
      

      【讨论】:

        【解决方案5】:

        最佳做法是使用片段而不是更改内容视图。

        在您的代码中,带有布局的 setContentView 每次都会重新创建(膨胀)您的所有视图,因此在 someBtn2 单击侦听器中调用 setContentView(R.layout.layout1) 将创建一个没有关联侦听器的新按钮。

        如果您不想使用片段,可以这样做:

        private View view1, view2;
        
        public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          view1 = getLayoutInflater().inflate(R.layout.layout1, null);
          view2 = getLayoutInflater().inflate(R.layout.layout2, null);
          setContentView(view1);
        

        听众将是:

        someBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setContentView(view2);
            }
        });
        
        
        someBtn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setContentView(view1);
            }
        });
        

        【讨论】:

        • 我想学分片方式,有什么简单的例子吗?
        • 请阅读developer.android.com/guide/components/fragments.html,并在 SDK 示例和 Android 支持库中查找示例(均可通过 Android SDK 管理器下载)
        • 如何使底部后退按钮返回到以前的布局而不是以前的活动?
        • 如果 button1 和 button2 在两个视图中具有相同的 id 怎么办?我实际上正在与这种情况作斗争。实际上,我的两个视图上都有多个按钮,如果他们做同样的工作,我不想为每个按钮写不同的监听器。有什么解决办法吗?
        • 您可以从膨胀视图 (view1.findViewById(...)) 中获取按钮,然后为其分配一个仅检查引用的侦听器 (view == view1)
        猜你喜欢
        • 2012-02-23
        • 1970-01-01
        • 1970-01-01
        • 2016-11-09
        • 2013-11-23
        • 2016-04-25
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        相关资源
        最近更新 更多