Search code examples
androidandroid-layoutdialogfragment

How to set FragmentDialog size to wrap to ListView


I have RecyclerView and when I long click on one of items FragmentDialog appears with custom layout: |@ text|. The problem is Fragment Dialog does not wrap area only to those 2 elements but takes almost entire screen place. The problem still appears even when I set the layout to wrap the content. Here is the problem: enter image description here

Here is RecyclerView custom_item XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center|left"
    android:padding="8dp"
    android:orientation="horizontal"
    android:clickable="true"
    android:background="?android:attr/selectableItemBackground">

    <!-- Option Icon -->
    <ImageView
        android:id="@+id/recipe_dialog_option_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:tint="@color/primary"
        android:layout_marginRight="4dp"
        android:src="@drawable/ic_email_48dp" />

    <!-- Text Option -->
    <TextView
        android:id="@+id/recipe_dialog_option_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="@color/primary_text"
        android:text="Dodaj do Ulubionych" />

</LinearLayout>

Here is FragmentDialog layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/dialog_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

and .class just in case:

package com.example.nazwamarki.myapplication.recipedialog;

import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

import com.example.nazwamarki.myapplication.R;

import java.util.ArrayList;

public class RecipeDialogFragment extends DialogFragment {

    private ArrayList<RecipeDialogItem> recipeDialogItems;
    private RecipeDialogAdapter recipeDialogAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);

        return inflater.inflate(R.layout.dialog_fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        recipeDialogItems = new ArrayList<>();
        RecyclerView dialogRecyclerView = (RecyclerView) view.findViewById(
                R.id.dialog_recycler_view);

        fillRecipeDialogArray(recipeDialogItems);

        recipeDialogAdapter = new RecipeDialogAdapter(getContext(), recipeDialogItems,
                R.layout.recipe_dialog_item);

        dialogRecyclerView.setHasFixedSize(true);
        dialogRecyclerView.setAdapter(recipeDialogAdapter);
        dialogRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    }

    private void fillRecipeDialogArray(ArrayList<RecipeDialogItem> recipeDialogitem) {
        RecipeDialogItem dialogItem;

        String[] names = new String[] {"Account", "Star"};
        int[] icons = new int[] {R.drawable.ic_account_plus_48dp, R.drawable.ic_account_star_48dp};

        for (int i = 0; i < 2; i++) {
            dialogItem = new RecipeDialogItem();
            dialogItem.setRowIcon(icons[i]);
            dialogItem.setRowOption(names[i]);
            recipeDialogitem.add(dialogItem);
        }
    }
}

Solution

  • Pass the ListView width to DialogFragment then do the following in onStart() of DialogFragment

    @Override
    public void onStart()
    {
      super.onStart();
    
      // safety check
      if (getDialog() == null)
        return;
    
      int dialogWidth = getArguments().getInt("width"); // specify a value here
      int dialogHeight = ... // specify a value here
    
      getDialog().getWindow().setLayout(dialogWidth, dialogHeight);
    
      // ... other stuff you want to do in your onStart() method
    }
    

    Best practice for Showing DialogFragment

    private void showDialog() {
        // DialogFragment.show() will take care of adding the fragment
        // in a transaction.  We also want to remove any currently showing
        // dialog, so make our own transaction and take care of that here.
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
        if (prev != null) {
            transaction.remove(prev);
        }
        transaction.addToBackStack(null);
    
        // Create and show the dialog.
        DialogFragment newFragment = RecipeDialogFragment.newInstance(width);
        newFragment.show(transaction, "dialog");
    }
    

    RecipeDialogFragment

        /**--Static factory method---
         * Create a new instance of RecipeDialogFragment, providing "width"
         * as arguments.
         */
        static RecipeDialogFragment newInstance(int width) {
            RecipeDialogFragment fragment = new RecipeDialogFragment();
            Bundle args = new Bundle(1);
            args.putInt("width", width);
            fragment.setArguments(args);
            return fragment;
        }