Chap 16 Challenge: Detail Display


#1

I put a click listener in CrimeFragment as below passing the photo path to my new CrimePhotoDialogFragment:

    mPhotoView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           if (mPhotoFile==null || !mPhotoFile.exists()) return;   //no photo
            FragmentManager fm = getFragmentManager();
            CrimePhotoDialogFragment dialog = CrimePhotoDialogFragment.newInstance(mPhotoFile.getPath());
            dialog.show(fm, PHOTO_TAG);
        }
    });

The dialog fragment uses the path and tries to fill the ImageView in the layout file:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.dialog_photo, container, false);
    Point size = new Point();
    getActivity().getWindowManager().getDefaultDisplay().getSize(size);
    Bitmap bitmap = PictureUtils.getScaledBitmap(mPath, size.x, size.y);
    mPhotoView = (ImageView)v.findViewById(R.id.dialog_photo);
    mPhotoView.setImageBitmap(bitmap);
    return v;
}

This opens just fine, but the displayed dialog isn’t full width, has a large white bar across the top (a header?) and the photo still has dark bars (padding) on the sides. I was hoping to get a dialog where the photo filled the available space. Here’s my layout:

Any suggestions?

Finally, when I press “back” to close the dialog, I get a warning:

W/InputEventReceiver: Attempted to finish an input event but the input event receiver has already been disposed.

Do I need to do something to close the dialog more cleanly?

Thanks very much


#2

Found a couple solutions. to remove the title and other decoration in the dialog, add the below to CrimePhotoDialogFragment:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    //use this to modify dialog characteristics
    Log.d("CriminalIntent", "CrimePhotoDialogFragment.onCreateDialog()");
    Dialog dialog = super.onCreateDialog(savedInstanceState);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.requestWindowFeature(Window.FEATURE_SWIPE_TO_DISMISS);
    return dialog;
}

Now you get a nice dialog that is just the image.

For another alternative, you can put the fragment in a full-screen view. This requires new code in the OnCclickListener in CrimeFragment:

    mPhotoView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("CrimeFragment", "click on photo");
            if (mPhotoFile==null || !mPhotoFile.exists()) return;   //no photo
            FragmentManager fm = getFragmentManager();
            CrimePhotoDialogFragment dialogFragment = CrimePhotoDialogFragment.newInstance(mPhotoFile.getPath());
            if (DO_DIALOG) {
                dialogFragment.show(fm, PHOTO_TAG);
            } else {
                //show in full screen
                android.support.v4.app.FragmentTransaction transaction = fm.beginTransaction();
                transaction.setTransition(android.support.v4.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                transaction.add(android.R.id.content, dialogFragment).addToBackStack(null).commit();
            }
        }
    });

#3

I put my code in “onCreateDialog” instead of “onCreateView” as follows:

public class ImageViewFragment extends DialogFragment {

    private static final String ARG_IMAGE = "image";

    private ImageView mImageZoom;

    public static ImageViewFragment newInstance(String imageFile) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_IMAGE, imageFile);

        ImageViewFragment fragment = new ImageViewFragment();
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        String imageFile = (String) getArguments().getSerializable(ARG_IMAGE);

        View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_zoom_image, null);

        Bitmap bitmap = getScaledBitmap(imageFile, getActivity());

        mImageZoom = (ImageView) v.findViewById(R.id.image_zoom_view);
        mImageZoom.setImageBitmap(bitmap);

        return new AlertDialog.Builder(getActivity())
                .setView(v)
                .create();
    }
}

I also used a simple xml layout with the scale type to “fixXY”:

This shows a picture as the whole dialog screen but I do still get the same warning as you.


#5

To get rid of ur padding problem, add this attribute in ur xml file
android:scaleType="fitXY"
Removing the title is easy, create the dialog using oncreateDialog, at the end dont add setTitle:)) like this code :slight_smile:

public Dialog onCreateDialog(Bundle savedInstanceState) {
String imageFile = (String) getArguments().getSerializable(ARG_IMAGE);

View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_zoom_image, null);

Bitmap bitmap = getScaledBitmap(imageFile, getActivity());

mImageZoom = (ImageView) v.findViewById(R.id.image_zoom_view);
mImageZoom.setImageBitmap(bitmap);

**return new AlertDialog.Builder(getActivity())**
      .setView(v)
        .create();

}


#6

Can you show me your entire Code for CrimePhotoDialogFragment?
Thanks alot in advance


#7

Can you show me your entire Code for CrimePhotoDialogFragment?


#8

Can you show me your entire Code for CrimePhotoDialogFragment?
Thanks alot


#9

Here is my solution for this challenge:

I set on click listener on mPhotoView:

public class CrimeFragment extends Fragment {
	private static final String DIALOG_PHOTO = "DialogPhoto";
	
...

mPhotoView.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View view) {
				FragmentManager manager = getFragmentManager();
				PhotoViewerFragment dialog = PhotoViewerFragment.newInstance(mPhotoFile);
				dialog.show(manager, DIALOG_PHOTO);
			}
		});

and here is PhotoViewerFragment.java:

package com.bignerdranch.android.criminalintent;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.io.File;

/**
 * Created by behin on 9/18/2017.
 */

public class PhotoViewerFragment extends DialogFragment {
	private static final String ARG_PHOTO_FILE = "photoFile";

	private ImageView mPhotoView;
	private File mPhotoFile;

	public static PhotoViewerFragment newInstance(File photoFile) {
		Bundle args = new Bundle();
		args.putSerializable(ARG_PHOTO_FILE, photoFile);

		PhotoViewerFragment fragment = new PhotoViewerFragment();
		fragment.setArguments(args);

		return fragment;
	}

	@Nullable
	@Override
	public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
		mPhotoFile = (File) getArguments().getSerializable(ARG_PHOTO_FILE);

		View view = inflater.inflate(R.layout.dialog_photo, container, false);

		mPhotoView = (ImageView) view.findViewById(R.id.photo_view_dialog);

		if (mPhotoFile == null || !mPhotoFile.exists()) {
			mPhotoView.setImageDrawable(null);
		} else {
			Bitmap bitmap = PictureUtils.getScaledBitmap(mPhotoFile.getPath(), getActivity());
			mPhotoView.setImageBitmap(bitmap);
		}

		return view;
	}
}

EDIT:

And finally, here is the layout “dialog_photo.xml”:

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

	<ImageView
		android:id="@+id/photo_view_dialog"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_gravity="center_horizontal|center_vertical"
		android:adjustViewBounds="false"
		android:background="@android:color/darker_gray"
		android:contentDescription="Evidence photo"/>

</FrameLayout>

#10

Hey guys, I searched around and found a simple solution for this problem by using ThemeOverlay.AppCompat.Dialog
Simply create the Dialog with that theme and there it’ll make the dialog just as big as the image need. Here is my onCreateDialog method:

public Dialog onCreateDialog(Bundle savedInstanceState) {
    File photoFile = (File) getArguments().getSerializable(ARG_FILE);

    View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_detail_photo, null);
    mPhoto = (ImageView) v.findViewById(R.id.detail_photo);

    Bitmap bitmap = PictureUtils.getScaledBitmap(photoFile.getPath(), getActivity());
    mPhoto.setImageBitmap(bitmap);

    return new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_AppCompat_Dialog)
            .setView(v)
            .create();
}

Credit: https://stackoverflow.com/a/29425992/75141