Search code examples
androidconstraintsandroid-constraintlayoutlandscape-portraitconstraintset

ConstraintLayout that should support portrait and landscape modes -with a button to toggle full screen


I'm trying to achieve the 4 cases of the image but with no success. Orange square is 40dp and used to toggle full screen. As you can see, in portrait\landscape mode: when orange button is pressed, the screen is toggled between 2 cases. Just take in mind that I can turn the smartphone back to portrait\landscape all the time and thus I think that the xml constraints are not really necessary.

I've tried this code but it doesn't work:

private void updateViews() {
    // Sets the orientation
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        mOrientation = Configuration.ORIENTATION_PORTRAIT;
    }
    else mOrientation = Configuration.ORIENTATION_LANDSCAPE;

    if (mConstraintParent == null) mConstraintParent = findViewById(R.id.constraint_parent);
    if (mButtonOrangeToggleFullScreen == null) mButtonOrangeToggleFullScreen = findViewById(R.id.buttonToggleFullScreen);

    // Handles button to toggle full screen
    mButtonOrangeToggleFullScreen.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            mFullScreen = !mFullScreen;
            setViewsDimensions();
        }
    });
    if (mGreen == null) mGreen = findViewById(R.id.green);
    if (mBlue == null) mBlue = findViewById(R.id.blue);
    if (mRed == null) mRed = findViewById(R.id.red);

    if (mOrientation == Configuration.ORIENTATION_PORTRAIT) {
        if (!mFullScreen) {
            ConstraintSet set = new ConstraintSet();
            set.clone(mConstraintParent);

            set.connect(mRed.getId(), ConstraintSet.TOP, mConstraintParent.getId(), ConstraintSet.TOP, 0);
            set.connect(mRed.getId(), ConstraintSet.BOTTOM, mBlue.getId(), ConstraintSet.TOP, 0);

            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.END, mRed.getId(), ConstraintSet.END, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.BOTTOM, mRed.getId(), ConstraintSet.BOTTOM, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.BOTTOM, mBlue.getId(), ConstraintSet.TOP, 0);

            set.connect(mBlue.getId(), ConstraintSet.LEFT, mConstraintParent.getId(), ConstraintSet.LEFT, 0);
            set.connect(mBlue.getId(), ConstraintSet.TOP, mRed.getId(), ConstraintSet.BOTTOM, 0);

            set.connect(mBlue.getId(), ConstraintSet.BOTTOM, mGreen.getId(), ConstraintSet.TOP, 0);
            set.connect(mGreen.getId(), ConstraintSet.BOTTOM, mConstraintParent.getId(), ConstraintSet.BOTTOM, 0);

            set.constrainPercentHeight(mRed.getId(), 0.7f);
            set.constrainPercentWidth(mRed.getId(), 1.0f);

            set.constrainPercentHeight(mBlue.getId(), 0.2f);
            set.constrainPercentWidth(mBlue.getId(), 1.0f);

            set.constrainPercentHeight(mGreen.getId(), 0.1f);
            set.constrainPercentWidth(mGreen.getId(), 1.0f);

            set.applyTo(mConstraintParent);

            mRed.setVisibility(View.VISIBLE);
            mBlue.setVisibility(View.VISIBLE);
            mGreen.setVisibility(View.VISIBLE);
        }
        else { // full screen portrait
            ConstraintSet set = new ConstraintSet();
            set.clone(mConstraintParent);
            set.connect(mRed.getId(), ConstraintSet.TOP, mConstraintParent.getId(), ConstraintSet.TOP, 0);
            set.connect(mRed.getId(), ConstraintSet.BOTTOM, mConstraintParent.getId(), ConstraintSet.BOTTOM, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.END, mConstraintParent.getId(), ConstraintSet.END, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.BOTTOM, mConstraintParent.getId(), ConstraintSet.BOTTOM, 0);
            set.constrainPercentHeight(mRed.getId(), 1.0f);
            set.constrainPercentWidth(mRed.getId(), 1.0f);
            set.constrainPercentHeight(mBlue.getId(), 0);
            set.constrainPercentWidth(mBlue.getId(), 0);
            set.constrainPercentHeight(mGreen.getId(), 0);
            set.constrainPercentWidth(mGreen.getId(), 0);
            set.applyTo(mConstraintParent);
            mRed.setVisibility(View.VISIBLE);
            mBlue.setVisibility(View.GONE);
            mGreen.setVisibility(View.GONE);
        }
    }
    else { // LANDSCAPE
        if (!mFullScreen) {
            ConstraintSet set = new ConstraintSet();
            set.clone(mConstraintParent);
            set.clear(mRed.getId());
            set.clear(mBlue.getId());

            set.connect(mRed.getId(), ConstraintSet.TOP, mConstraintParent.getId(), ConstraintSet.TOP, 0);
            set.connect(mRed.getId(), ConstraintSet.RIGHT, mBlue.getId(), ConstraintSet.LEFT, 0);

            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.END, mRed.getId(), ConstraintSet.END, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.BOTTOM, mRed.getId(), ConstraintSet.BOTTOM, 0);

            set.connect(mBlue.getId(), ConstraintSet.LEFT, mRed.getId(), ConstraintSet.RIGHT, 0);
            set.connect(mBlue.getId(), ConstraintSet.TOP, mConstraintParent.getId(), ConstraintSet.TOP, 0);

            set.connect(mRed.getId(), ConstraintSet.BOTTOM, mGreen.getId(), ConstraintSet.TOP, 0);
            set.connect(mGreen.getId(), ConstraintSet.BOTTOM, mConstraintParent.getId(), ConstraintSet.BOTTOM, 0);

            set.constrainPercentHeight(mRed.getId(), 0.9f);
            set.constrainPercentWidth(mRed.getId(), 0.8f);

            mBlue.setLayoutParams(new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_CONSTRAINT_PERCENT, ConstraintLayout.LayoutParams.MATCH_CONSTRAINT_PERCENT));
            set.constrainPercentHeight(mBlue.getId(), 0.9f);
            set.constrainPercentWidth(mBlue.getId(), 0.2f);

            set.constrainPercentHeight(mGreen.getId(), 0.1f);
            set.constrainPercentWidth(mGreen.getId(), 1.0f);

            set.applyTo(mConstraintParent);

            mRed.setVisibility(View.VISIBLE);
            mBlue.setVisibility(View.VISIBLE);
            mGreen.setVisibility(View.VISIBLE);
        }
        else { // full screen landscape
            ConstraintSet set = new ConstraintSet();
            set.clone(mConstraintParent);
            set.connect(mRed.getId(), ConstraintSet.TOP, mConstraintParent.getId(), ConstraintSet.TOP, 0);
            set.connect(mRed.getId(), ConstraintSet.BOTTOM, mConstraintParent.getId(), ConstraintSet.BOTTOM, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.END, mConstraintParent.getId(), ConstraintSet.END, 0);
            set.connect(mButtonOrangeToggleFullScreen.getId(), ConstraintSet.BOTTOM, mConstraintParent.getId(), ConstraintSet.BOTTOM, 0);
            set.constrainPercentHeight(mRed.getId(), 1.0f);
            set.constrainPercentWidth(mRed.getId(), 1.0f);
            set.constrainPercentHeight(mBlue.getId(), 0);
            set.constrainPercentWidth(mBlue.getId(), 0);
            set.constrainPercentHeight(mGreen.getId(), 0);
            set.constrainPercentWidth(mGreen.getId(), 0);
            set.applyTo(mConstraintParent);
            mRed.setVisibility(View.VISIBLE);
            mBlue.setVisibility(View.GONE);
            mGreen.setVisibility(View.GONE);

        }
    }
}

Here is the xml I use (not sure if relevant because I override it in code)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/constraint_parent">

    <ImageView
        android:id="@+id/red"
        android:layout_width="0dp"
        android:layout_height="0dp"
        ads:layout_constraintTop_toTopOf="@+id/constraint_parent"
        ads:layout_constraintEnd_toEndOf="@+id/constraint_parent"
        ads:layout_constraintStart_toStartOf="@id/constraint_parent"
        android:background="@color/custom_red"
        ads:layout_constraintBottom_toTopOf="@+id/blue"
        app:layout_constraintHeight_percent=".7"
        app:layout_constraintWidth_percent="1.0"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintWidth_default="percent"
        tools:layout_editor_absoluteX="5dp" />

    <ImageButton
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginRight="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginBottom="5dp"
        android:background="@android:color/holo_orange_dark"
        ads:layout_constraintEnd_toEndOf="@+id/red"
        ads:layout_constraintBottom_toBottomOf="@+id/red"
        android:id="@+id/buttonToggleFullScreen"/>

    <ImageView
        android:id="@+id/blue"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#550000ff"
        app:layout_constraintHeight_percent=".2"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintWidth_default="percent"
        ads:layout_constraintLeft_toLeftOf="@+id/constraint_parent"
        ads:layout_constraintTop_toBottomOf="@+id/red"
        ads:layout_constraintBottom_toTopOf="@+id/green"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintHeight_percent=".1"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintWidth_default="percent"
        android:background="@color/green_shiny"
        android:orientation="vertical"
        ads:layout_constraintBottom_toBottomOf="@+id/constraint_parent"
        android:id="@+id/green">
    </LinearLayout>
</android.support.constraint.ConstraintLayout>

Please help me to achieve the desired result.

enter image description here


Solution

  • This can be done fairly simply using XML layouts for both portrait and landscape orientation and using weights to define the relative sizes of the views. When the toggle button is pressed, you make the blue/green views VISIBLE or GONE depending on the full screen state. The red view then resizes to fill the space vacated by the blue/green views.

    Note the use of onSaveInstanceState to preserve the full screen state over configuration changes.

    MainActivity.java:

    package com.example.test;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.ImageButton;
    import android.widget.ImageView;
    
    public class MainActivity extends AppCompatActivity {
    
        private boolean mFullScreen = false;
        private ImageView mBlue;
    
        private ImageView mGreen;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ImageButton toggleButton = findViewById(R.id.toggle_button);
            mBlue = findViewById(R.id.blue);
            mGreen = findViewById(R.id.green);
            if (savedInstanceState != null) {
                setFullScreen(savedInstanceState.getBoolean("mFullScreen", false));
            }
            toggleButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    setFullScreen(!mFullScreen);
                }
            });
        }
    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putBoolean("mFullScreen", mFullScreen);
        }
    
        private void setFullScreen(boolean fullScreen) {
            mFullScreen = fullScreen;
            mBlue.setVisibility(mFullScreen ? View.GONE : View.VISIBLE);
            mGreen.setVisibility(mFullScreen ? View.GONE : View.VISIBLE);
        }
    }
    

    res/layout/activity_main.xml (portrait):

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <ImageView
            android:id="@+id/red"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#ffff0000"
            app:layout_constraintBottom_toTopOf="@+id/blue"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_weight="0.7" />
    
        <ImageView
            android:id="@+id/blue"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#ff0000ff"
            app:layout_constraintBottom_toTopOf="@+id/green"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/red"
            app:layout_constraintVertical_weight="0.2" />
    
        <ImageView
            android:id="@+id/green"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#ff00ff00"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/blue"
            app:layout_constraintVertical_weight="0.1" />
    
        <ImageButton
            android:id="@+id/toggle_button"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="15dp"
            android:background="#ffffa000"
            app:layout_constraintBottom_toBottomOf="@id/red"
            app:layout_constraintEnd_toEndOf="@id/red"/>
    
    </android.support.constraint.ConstraintLayout>
    

    res/layout-land/activity_main.xml: (landscape)

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <ImageView
            android:id="@+id/red"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#ffff0000"
            app:layout_constraintBottom_toTopOf="@+id/green"
            app:layout_constraintEnd_toStartOf="@+id/blue"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_weight="0.9"
            app:layout_constraintHorizontal_weight="0.8"/>
    
        <ImageView
            android:id="@+id/blue"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="#ff0000ff"
            app:layout_constraintBottom_toTopOf="@+id/green"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/red"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_weight="0.9"
            app:layout_constraintHorizontal_weight="0.2"/>
    
        <ImageView
            android:id="@+id/green"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#ff00ff00"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/red"
            app:layout_constraintVertical_weight="0.1" />
    
        <ImageButton
            android:id="@+id/toggle_button"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="15dp"
            android:background="#ffffa000"
            app:layout_constraintBottom_toBottomOf="@id/red"
            app:layout_constraintEnd_toEndOf="@id/red"/>
    
    </android.support.constraint.ConstraintLayout>