Search code examples
androidandroid-fragmentsandroid-dialogfragmentandroid-styles

Why my DialogFragment style is wrong when I show it from different Activity?


I am facing a strange behaviour using DialogFragment with custom view.

When I show the dialog from another dialog of an activity everything is fine but when I show it from another fragment (and different activity) the style is messed up and I can't see the SearchView, the RecyclerView item decorators and the text of the TextViews in it.

Code for the dialog:

public class MyDialogFragment extends DialogFragment 
{
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.My_Dialog);

        LayoutInflater inflater = LayoutInflater.from(getContext());
        View view = inflater.inflate(R.layout.fragment_my, (ViewGroup) getActivity().findViewById(android.R.id.content), false);
        builder.setView(view);

        final SearchView searchView = (SearchView) view.findViewById(R.id.searchView);
        final RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(adapter);
        HorizontalDividerDecoration.Builder dividerBuilder = new HorizontalDividerDecoration.Builder(getContext());
        recyclerView.addItemDecoration(dividerBuilder.build());

        // ...

        builder.setNegativeButton(android.R.string.cancel, null);
        final AlertDialog dialog = builder.create();

        return dialog;
    }
}

fragment_my.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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">

    <android.support.v7.widget.SearchView
        android:id="@+id/searchView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </android.support.v7.widget.SearchView>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/searchView"
        android:scrollbarStyle="insideOverlay"
        app:layoutManager="LinearLayoutManager"
        tools:listitem="@layout/my_item"/>

</RelativeLayout>

The style used:

<style name="My.Dialog" parent="Theme.AppCompat.Light.Dialog.Alert">

</style>

my_item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    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">

    <data>

        <import type="android.view.View"/>

        <variable
            name="bindObject"
            type="com.spiral_root.app.pecunia.adapter.MyBind"/>
    </data>

    <RelativeLayout
        android:id="@+id/containerLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@{bindObject.selected ? @color/lightGrey : @color/transparent}"
        android:clickable="true"
        android:foreground="?android:selectableItemBackground"
        android:padding="@dimen/dimen_5dp">

        <FrameLayout
            android:id="@+id/selectedContainer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true">

            <ImageView
                android:id="@+id/selectedImageView"
                style="@style/CheckedIcon"
                android:layout_marginEnd="@dimen/dimen_5dp"
                android:tint="@color/source"
                android:visibility="@{bindObject.selected ? View.VISIBLE : View.GONE}"
                app:srcCompat="@drawable/check_circle_white_24dp"/>

        </FrameLayout>

        <ImageView
            android:id="@+id/imageView"
            style="@style/CurrencyFlag"
            android:layout_marginStart="@dimen/dimen_5dp"
            android:src="@{bindObject.flagResourceId}"
            tools:src="@drawable/flag_eur"/>

        <TextView
            android:id="@+id/nameTextView"
            style="@style/WrappedText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="@dimen/dimen_5dp"
            android:layout_marginStart="@dimen/dimen_10dp"
            android:layout_toEndOf="@id/imageView"
            android:layout_toStartOf="@id/selectedContainer"
            android:text="@{bindObject.name}"
            android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
            tools:text="Name"/>

        <TextView
            android:id="@+id/symbolTextView"
            style="@style/WrappedText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignStart="@id/nameTextView"
            android:layout_below="@id/nameTextView"
            android:layout_marginTop="@dimen/dimen_7dp"
            android:layout_toEndOf="@id/imageView"
            android:text="@{bindObject.symbol}"
            android:textAppearance="@style/TextAppearance.AppCompat.Caption"
            android:textSize="14sp"
            tools:text="$"/>

        <TextView
            android:id="@+id/codeTextView"
            style="@style/WrappedText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@id/symbolTextView"
            android:layout_below="@id/nameTextView"
            android:layout_marginStart="@dimen/dimen_5dp"
            android:layout_toEndOf="@id/symbolTextView"
            android:text="@{@string/parenthesis(bindObject.code)}"
            android:textAppearance="@style/Currency.Dialog.Caption"
            android:textSize="14sp"
            tools:text="USD"/>

    </RelativeLayout>

</layout>

Working code (from another dialog):

public class ParentDialogFragment extends DialogFragment
{
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.fragment_parent, (ViewGroup) getActivity().findViewById(android.R.id.content), false);
        builder.setView(view);

        final Button button = (Button) view.findViewById(R.id.currencyButton);
        button.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                MyDialogFragment dialog = MyDialogFragment.newInstance(selectedCode, new MyDialogFragment.Listener()
                {
                    @Override
                    public void select(CurrencyBind item)
                    {
                        // ...
                    }
                });
                dialog.show(getFragmentManager(), "my_dialog");
            }
        });
    }
}

ParentDialogFragment is shown from ParentListFragment

public class ParentListFragment extends Fragment
{
    // ...

    private void showSourceDialog(SourceEntity entity)
    {
        ParentDialogFragment dialog = ParentDialogFragment.newInstance(entity, new ParentDialogFragment.Callback()
        {
            // ...
        });
        dialog.show(getFragmentManager(), "parent_dialog");
    }
}

ParentListFragment is the content of ParentListWizardActivity which simply loads the fragment and has this style:

<!-- AndroidManifest.xml -->
<activity android:name=".activity.ParentListWizardActivity"
    android:label="@string/title_activity_parent_list_wizard"
    android:theme="@style/AppTheme.NoActionBar">
</activity>


<!-- styles.xml -->
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primaryDark</item>
    <item name="colorAccent">@color/secondary</item>
</style>

<style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

And the result is this:

Working dialog fragment

When it doesn't work I have this situation:

public class MyWizardFragment extends ParallaxSlideFragment
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.fragment_my_wizard, container, false);

        actionButton = (Button) rootView.findViewById(R.id.actionButton);
        actionButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                MyDialogFragment dialog = MyDialogFragment.newInstance(preferenceManager.getDefaultCode(), new MyDialogFragment.Listener()
                {
                    @Override
                    public void select(MyBind item)
                    {
                        // ...
                    }
                });
                dialog.show(getFragmentManager(), "my_dialog");
            }
        });

        return rootView;
    }
}

MyWizardFragment is injected by the activity WizardActivity which has the following style:

<activity
    android:name=".activity.WizardActivity"
    android:label="@string/app_name"
    android:theme="@style/Theme.Intro">
</activity>

<style name="Theme.Intro" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowIsTranslucent">true</item>
</style>

And the result is this:

Wrong dialog fragment style

I don't understand if it's something about the style or the fragment manager or any other stuff.

Thanks


Solution

  • I finally solved my problem.

    The issue was not the AlertDialog but the style of the custom view, which apparentely, is not inherited from the dialog but you have specify.

    I replaced:

    LayoutInflater inflater = LayoutInflater.from(getContext());
    

    With:

    LayoutInflater inflater = LayoutInflater.from(new ContextThemeWrapper(getContext(), R.style.My_Dialog));
    

    Like this answer: https://stackoverflow.com/a/17433764/3853058

    And everything now is fine