Search code examples
androiddialogscreen-orientationcustomdialog

Custom Dialog with listview on orientation change (landscape mode)


I wanted my custom dialog to work in both portrait and landscape mode. for that, I found a solution to create the XML in the layout-land folder as well. so, I copied the layout and pasted the same in the layout-land folder and made a modification(added a scroll view). Still, it is not working as I expected. in spite of adding scrollview the dialog does not scroll completely.

The dialog also contains a list view.

my layout-land/dialog.xml is as follows.

<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:id="@+id/main_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/transparent"
    tools:context="customviews.VeriDocDialog">

    <android.support.constraint.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:background="@color/transparent"
        app:layout_constraintBottom_toBottomOf="@id/center_fab_view"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

    </android.support.constraint.ConstraintLayout>

    <android.support.constraint.ConstraintLayout
        android:id="@+id/top_fab_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:elevation="1dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/top_fab"
            android:layout_width="56dp"
            android:layout_height="56dp"
            android:background="@drawable/round_bg"
            android:scaleType="center"
            android:src="@drawable/share_24" />

    </android.support.constraint.ConstraintLayout>

    <View
        android:id="@+id/center_fab_view"
        android:layout_width="wrap_content"
        android:layout_height="1dp"
        app:layout_constraintCircle="@id/top_fab_layout" />

    <android.support.constraint.ConstraintLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/white"
        app:layout_constraintBottom_toBottomOf="@id/top_fab_layout"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/center_fab_view">

    </android.support.constraint.ConstraintLayout>

    <ImageView
        android:id="@+id/img_close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:elevation="5dp"
        android:src="@drawable/cross_30"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/center_fab_view" />

    <ScrollView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/top_fab_layout">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            >

            <TextView
                android:id="@+id/dialog_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:layout_margin="10dp"
                android:textColor="@color/primary_text"
                android:textSize="@dimen/textsize_xlarge"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="TITLE" />

            <ImageView
                android:id="@+id/img"
                android:layout_width="45dp"
                android:layout_height="wrap_content"
                android:layout_below="@id/dialog_title"
                android:layout_centerHorizontal="true"
                android:src="@drawable/hr"
                app:layout_constraintBottom_toTopOf="@id/tv_instruction"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/dialog_title" />

            <TextView
                android:id="@+id/tv_instruction"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/img"
                android:layout_centerHorizontal="true"
                android:layout_margin="5dp"
                android:gravity="center"
                android:lines="2"
                android:text="invited friends \n to win more scrathches"
                android:textColor="@color/primary_text"
                android:textSize="@dimen/textsize_medium"
                app:layout_constraintBottom_toTopOf="@id/center_text"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/img" />

            <RelativeLayout
                android:id="@+id/center_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/tv_instruction"
                android:layout_centerHorizontal="true"
                android:layout_margin="5dp"
                app:layout_constraintBottom_toTopOf="@id/listview"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_instruction">

                <TextView
                    android:id="@+id/tv_equation"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:gravity="center"
                    android:lines="2"
                    android:text="invite 1 = 2 Scratches"
                    android:textColor="@color/primary_text"
                    android:textSize="@dimen/textsize_medium" />

                <TextView
                    android:id="@+id/tv_highlighted_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:gravity="center"
                    android:padding="5dp"
                    android:text="Facebook"
                    android:textColor="@color/blue_A200"
                    android:textSize="@dimen/textsize_regular"
                    android:visibility="gone" />

            </RelativeLayout>

            <View
                android:id="@+id/view_above_listView"
                android:layout_width="wrap_content"
                android:layout_height="3dp"
                android:layout_above="@+id/listview"
                android:background="@drawable/primary_gradient_horizontal"
                app:layout_constraintBottom_toTopOf="@id/listview" />

            <ListView
                android:id="@+id/listview"
                android:layout_width="match_parent"
                android:layout_height="160dp"
                android:layout_below="@id/center_text"
                android:divider="@color/selected_gray"
                android:dividerHeight="1dp"
                app:layout_constraintBottom_toTopOf="@id/view_above_button"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/center_text" />

            <TextView
                android:id="@+id/tv_loading"
                android:layout_width="match_parent"
                android:layout_height="160dp"
                android:layout_below="@id/center_text"
                android:gravity="center"
                android:text=""
                android:textColor="@color/primary"
                android:textSize="16sp"
                android:visibility="gone"
                app:layout_constraintBottom_toTopOf="@id/view_above_button"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/center_text" />

            <View
                android:id="@+id/view_above_button"
                android:layout_width="wrap_content"
                android:layout_height="3dp"
                android:layout_above="@+id/btn_bottom"
                android:background="@drawable/primary_gradient_horizontal"
                app:layout_constraintBottom_toTopOf="@id/btn_bottom" />

            <Button
                android:id="@+id/btn_bottom"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/listview"
                android:background="@color/selected_gray"
                android:text="invite"
                android:textColor="@color/primary_text"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/listview" />

        </RelativeLayout>

    </ScrollView>

</android.support.constraint.ConstraintLayout>

How Dialog looks in Portrait mode see here Vs. How Dialog looks in landscape mode see here

my VeriDocDialog.java code is as follows

public class VeriDocDialog extends Dialog {
     private View dialogView;

    public VeriDocDialog(@NonNull Context context, String dialogType, int iconDrawableId, String instructions,String bottomText, List<Contact> contactList, String buttonText) {

        super(context);
        this.context = context;
        this.dialogType = dialogType;
        this.iconDrawableId = iconDrawableId;
        this.instruction = instructions;
        this.buttonText = buttonText;
        this.contactList = contactList;
        this.bottomText = bottomText;

        setupVeriDocDialog();
    }

    public VeriDocDialog(@NonNull Context context, String dialogType, int iconDrawableId, String instructions, String bottomText, List<ResolveInfo> shareList, String buttonText, Intent shareIntent) {

        super(context);
        this.context = context;
        this.dialogType = dialogType;
        this.iconDrawableId = iconDrawableId;
        this.instruction = instructions;
        this.buttonText = buttonText;
        this.shareList = shareList;
        this.bottomText = bottomText;
        this.shareIntent = shareIntent;

        setupVeriDocDialog();
    }

    private void setupVeriDocDialog() {

        if (getWindow() != null) {
            getWindow().setBackgroundDrawableResource (R.color.transparent);
            getWindow().setGravity(Gravity.CENTER);
            getWindow().getAttributes().windowAnimations = R.style.dialogAnimation;
            requestWindowFeature(Window.FEATURE_NO_TITLE);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         dialogView = getLayoutInflater().inflate(R.layout.dialog_veri_doc, null);
         setContentView(dialogView);

         bindView();
         initialise(dialogType);
     }

     //.... and other methods .....
}    

How I call this dialog from my activity :

private void displayInviteDialog() {
    contactList = new ArrayList<>();

    inviteDialog = new VeriDocDialog(ScratchAndWinActivity.this,
            VeriDocDialog.TYPE_INVITE,
            R.drawable.invite_32,
            getString(R.string.str_invite_instruction),
            getString(R.string.str_equation_invite),
            contactList, VeriDocDialog.TYPE_INVITE);


    inviteDialog.show();
}

Problem is, layout is not proper. I have mentioned the xml layout in land folder too.and also put the views inside scrollview but still the scrollview does not scroll the dialog to its bottom.

is it because of listview? if yes then please provide me some solution. and if not what can be the cause and How to overcome this situation? any help would be appreciated.

and when I try to open the dialog when the orientation is landscape, the xml from the land folder is inflated. but, when I open the dialog in portrait and after that, I change the orientation, the xml is same(same in regular layout not from the land folder).

Please help me with this problem.


Solution

  • This is because your Dialog does not recreate after screen orientation change. And it is having old resource layout.

    For solution, you can detect orientation change and recreate dialog if already opened. You can use onConfigurationChanged in your Activity for detecting orientation change.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
        }
    
        if (inviteDialog !=null && inviteDialog.isShowing()){
            inviteDialog .dismiss(); 
            displayInviteDialog();
        }
    }
    
    private void displayInviteDialog() {
        contactList = new ArrayList<>();
    
        inviteDialog = new VeriDocDialog(ScratchAndWinActivity.this,
                VeriDocDialog.TYPE_INVITE,
                R.drawable.invite_32,
                getString(R.string.str_invite_instruction),
                getString(R.string.str_equation_invite),
                contactList, VeriDocDialog.TYPE_INVITE);
    
    
        inviteDialog.show();
    }
    

    And edit your manifest activity registration a bit.

    <activity android:name=".YourActivity"
          android:configChanges="orientation">
    

    Suggestion:

    1> You should use match_parent for the parent layout element of Dialog.

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    

    2> Set Dialog height & width match_parent programatically also. See this answer

    Update

    Use NestedScrollView instead of ScrollView because ListView itself has scrolling property, that will cause conflicts.

    Update

    I created a sample, that is working fine in both the mode, you will be amazed to know I did not set any special property to dialog to make that work. Here is the sample.

    import android.app.Dialog;
    import android.content.Context;
    import android.os.Bundle;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import com.innovanathinklabs.sample.R;
    
    /**
     * Created by KHEMRAJ on 8/29/2018.
     */
    public class ListActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            MyDialog dialog = new MyDialog(this);
            dialog.show();
            Window window = dialog.getWindow();
            window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
        }
    
        public static class MyDialog extends Dialog {
            String[] mobileArray = {
                    "Android", "IPhone", "WindowsMobile", "Blackberry",
                    "WebOS", "Ubuntu", "Windows7", "Max OS X", "Android", "IPhone", "WindowsMobile", "Blackberry",
                    "WebOS", "Ubuntu", "Windows7", "Max OS X", "Android", "IPhone", "WindowsMobile", "Blackberry",
                    "WebOS", "Ubuntu", "Windows7", "Max OS X",
            };
    
            public MyDialog(@NonNull Context context) {
                super(context);
            }
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.dialog_sample);
                ArrayAdapter adapter = new ArrayAdapter<>(getContext(),
                        R.layout.row_list, mobileArray);
                ListView listView = findViewById(R.id.listView);
                listView.setAdapter(adapter);
            }
        }
    }
    

    and dialog_sample.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical">
    
        <!--in this view, horizontal and vertical both dialog has scrollable List and other view looks static-->
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="5">
    
            <!--place your all top content here-->
        </LinearLayout>
    
        <!--weight 1 is giving List view the available space. -->
    
        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="5"/>
    
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/app_name"/>
    
    </LinearLayout>
    

    Here is output

    enter image description here

    enter image description here

    Please note that.

    • I did not to handle orientation, its working as expected.
    • I set weight to child views. So it is getting fit automatically in both orientation.
    • Issue in your xml layout was that you did not use weights/percentage, so content goes outside screen.