Sathish Kumar
Sathish Kumar

Reputation: 957

How to Split the Options menu like Google chrome broswer

How to split a menu like chrome browser as shown in the image:

image

This is my actual code

<menu 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"
    tools:context="materialtest.vivz.slidenerd.activities.MainActivity">

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />

</menu>

Upvotes: 6

Views: 1121

Answers (3)

Zain
Zain

Reputation: 40830

You can use a custom DialogFragment with a dialog window that has a limited size and biased to the top end of the screen using the gravity attribute.

Like normal fragments, DialogFragment takes in any custom layout in onCreateView.

Animation: The dialog window can have a customized style with windowEnterAnimation and windowExitAnimation to simulate the animation of showing/dismissing the menu.

Here's the demo:

class OptionsMenuDialog : DialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view = inflater.inflate(R.layout.dialog_options_menu, container, false)
        return view
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)
        // adding dialog animation
        dialog.window!!.attributes!!.windowAnimations = R.style.DialogAnimation
        return dialog
    }

    override fun onStart() {
        super.onStart()

        dialog!!.window!!.let {
            val params = it.attributes
            // Change the dialog size
            params.width = 600
            params.height = 1000
            // Bias the dialog to the top|end of the screen
            params.gravity = Gravity.TOP or Gravity.END
            it.attributes = params
        }

    }

}

Java version:

public class OptionsMenuDialog extends DialogFragment {

    @Nullable
    @org.jetbrains.annotations.Nullable
    @Override
    public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        return inflater.inflate(
                R.layout.dialog_options_menu, container,
                false
        );
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Dialog dialog =super.onCreateDialog(savedInstanceState);
        dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
        return dialog;
    }

    @Override
    public void onStart() {
        Window window = getDialog().getWindow();
        WindowManager.LayoutParams attributes = window.getAttributes();
        // Change dialog size
        attributes.width = 600;
        attributes.height = 1000;
        // Bias the dialog to the top|end of the screen
        attributes.gravity = Gravity.TOP | Gravity.END;
        window.setAttributes(attributes);
        super.onStart();
    }
}

The DialogAnimation:

    <style name="DialogAnimation">
        <item name="android:windowEnterAnimation">@anim/anim_in</item>
        <item name="android:windowExitAnimation">@anim/anim_out</item>
    </style>

Animations:

anim_in:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <scale
        android:duration="50"
        android:fromXScale="1.0"
        android:fromYScale="0.0"
        android:toXScale="1.0"
        android:toYScale="1.0" />
</set>

anim_out:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <scale
        android:duration="50"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="1.0"
        android:toYScale="0.0" />
</set>

And the layout:

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageButton
        android:id="@+id/back"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:padding="10dp"
        android:src="@drawable/baseline_arrow_back_24"
        app:layout_constraintEnd_toStartOf="@+id/bookmark"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@+id/bookmark"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:padding="10dp"
        android:src="@drawable/baseline_star_outline_24"
        app:layout_constraintEnd_toStartOf="@+id/refresh"
        app:layout_constraintStart_toEndOf="@+id/back"
        app:layout_constraintTop_toTopOf="parent" />


    <ImageButton
        android:id="@+id/refresh"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="?android:attr/selectableItemBackground"
        android:padding="10dp"
        android:src="@drawable/baseline_refresh_24"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/bookmark"
        app:layout_constraintTop_toTopOf="parent" />


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_margin="8dp"
        android:fillViewport="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/refresh">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginVertical="16dp"
                android:text="New tab"
                android:textSize="18sp" />
        </LinearLayout>

    </ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

You can use RecyclerView for efficiency; just used ScrollView for simplicity.

Edit:

params.width = 600, params.height = 1000 both are overlapping small devices (small DP devices) in the size of the Options menu. Any better option to overcome this?

You'd create an XML value for both for different screen sizes; usually in values/dimens.xml

The default dimens.xml would be something like:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="dialog_height">150dp</dimen>
    <dimen name="dialog_width">100dp</dimen>
</resources>

The documentation show typical screen sizes that you would override their corresponding dimen resources:

Here's how other smallest width values correspond to typical screen sizes:

  • 320dp: Typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc.)
  • 480dp: Large phone screen ~5" (480x800 mdpi)
  • 600dp: 7” tablet (600x1024 mdpi)
  • 720dp: 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc.)

Android studio can generate that automatically with: File >> New >> Values Resource File

Then you can specify the desired screen width/height that you need to have a different size.

enter image description here

This post has more in depth how to handle that.

Eventually you'd retrieve them in the dialog fragment like, and that will take care of the device width/height to pick the appropriate value:

// Kotlin
override fun onStart() {
    super.onStart()

    val density = Resources.getSystem().displayMetrics.density
    val width = (resources.getDimension(R.dimen.dialog_width) * density).toInt()
    val height = (resources.getDimension(R.dimen.dialog_height) * density).toInt()

    dialog!!.window!!.let {
        val params = it.attributes
        // Change dialog size
        params.width = width
        params.height = height
        // Bias the dialog to the top|end of the screen
        params.gravity = Gravity.TOP or Gravity.END
        it.attributes = params
    }

}

// Java

@Override
public void onStart() {
    Window window = getDialog().getWindow();
    WindowManager.LayoutParams attributes = window.getAttributes();

    float density = Resources.getSystem().getDisplayMetrics().density;
    int width = (int) (getResources().getDimension(R.dimen.dialog_width) * density);
    int height = (int) (getResources().getDimension(R.dimen.dialog_height) * density);

    attributes.width = width;
    attributes.height = height;
    // Bias the dialog to the top|end of the screen
    attributes.gravity = Gravity.TOP | Gravity.END;
    window.setAttributes(attributes);
    super.onStart();
}

Upvotes: 1

Sikander Baloch
Sikander Baloch

Reputation: 11

Try the following code:

<menu 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"
    tools:context="materialtest.vivz.slidenerd.activities.MainActivity">

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_new"
        android:orderInCategory="101"
        android:title="@string/action_new"
        app:showAsAction="never" />

</menu>

<!-- Second menu -->
<menu 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"
    tools:context="materialtest.vivz.slidenerd.activities.MainActivity">

    <item
        android:id="@+id/action_save"
        android:orderInCategory="102"
        android:title="@string/action_save"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_print"
        android:orderInCategory="103"
        android:title="@string/action_print"
        app:showAsAction="never" />

</menu>

Upvotes: 0

Alican Temel
Alican Temel

Reputation: 1318

You can implement dialogFragment and you can locate on the screen where you want.

Here is an example :

http://www.androidbegin.com/tutorial/android-dialogfragment-tutorial/

You can change the position of the dialog. You can find it out how it works here :

Changing position of the Dialog on screen android

Upvotes: 3

Related Questions