How to set layout dynamically in android

Well, Suppose there is an Activity called MainActivity and there are two layouts called layout1 and layout2 both have few buttons. By default MainActivity layout is layout1 like following:

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

Now what I did actually is by clicking a button in layout1 the second layout is set like following:

  • Google Android platform financially interesting already?
  • How to replace the activity's fragment from the fragment itself?
  • Android marshmallow request permission?
  • how can meteor be coupled to an android app?
  • Android - how to define ShapeDrawables programmatically?
  • How to capitalize every letter in an Android EditText?
  •     someBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setContentView(R.layout.layout2);
            }
        });
    

    There are another button in layout2 to return back to layout1 like following:

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

    Problem is when I returned back to layout1 then OnClickListener of someBtn1 is not working. It seems I need to set OnClickListener again for someBtn1 of layout1.
    How I can write code to make them work perfectly with best practices ?

    Related posts:

    How to get accent color programmatically?
    How to make ConstraintLayout work with percentage values?
    File Explorer always empty in Eclipse
    How to make sure that you don't start a service twice android
    List intent filters for installed packages
    Spinner inner padding is larger on Android 6.0.1
  • EditText hint doesn't show
  • Android appcompat-v7:21.0.0 change material checkbox colors
  • org.apache.http packages removed in API level 23. What is the alternative?
  • Android Camera - Preview zooms in when recording video
  • Open-sourcing a mobile app
  • adb push/pull with progress bar
  • 5 Solutions collect form web for “How to set layout dynamically in android”

    The best practice is to use fragments instead of change the content view.

    In your code, setContentView with layouts recreate (inflate) all your views every time, so the call setContentView(R.layout.layout1) in someBtn2 click listener will create a new button without the associated listener.

    If you don’t want to use fragments you can do this:

    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);
    

    The listeners will be:

    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);
        }
    });
    

    If you just want to play around with your current code, a solution for your problem is that the listeners must be redeclared when the layout changes, as follows:

    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);
                }
            });
        }
    });
    

    An alternative to avoid declaring the listeners twice is to declare two methods to handle the layout changes and use the onClick property of the button in each of the layouts, for example:

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

    In layout1.xml:

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

    In layout2.xml:

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

    However, if you want to follow best practices, the best practice is not to mix layouts in the same activity, but instead declare two different activities (each one with its own layout) and call one activity or the other depending on the button that was clicked. Suppose that you are in Activity1 and want to call Activity2, then go back to Activity1:

    In Activity1.java:

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

    In Activity2.java:

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

    One way of doing this is loading both views in onCreate(...), and then switching between them by making the one you don’t want invisible. Something like the following:

    @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();
    

    At the time you callback layout1, data must be set again.

    You could merge both layouts in one and then use ViewFlipper to switch between them.

    When you are seting layout2, you should also set up OnClickListener to someBtn1 and vice versa, I’d suggest something like this. But as in prevoius answer, in general you should avoid mixing layouts in such manner.

    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
        }
    }
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.