FileDocCategorySizeDatePackage
PhotoViewFragment.javaAPI DocAndroid 5.1 API21732Thu Mar 12 22:22:52 GMT 2015com.android.ex.photo.fragments

PhotoViewFragment

public class PhotoViewFragment extends android.support.v4.app.Fragment implements com.android.ex.photo.PhotoViewCallbacks.OnScreenListener, com.android.ex.photo.PhotoViewCallbacks.CursorChangedListener, LoaderManager.LoaderCallbacks, android.view.View.OnClickListener
Displays a photo.

Fields Summary
protected static final String
STATE_INTENT_KEY
protected static final String
ARG_INTENT
protected static final String
ARG_POSITION
protected static final String
ARG_SHOW_SPINNER
protected String
mResolvedPhotoUri
The URL of a photo to display
protected String
mThumbnailUri
protected android.content.Intent
mIntent
The intent we were launched with
protected com.android.ex.photo.PhotoViewCallbacks
mCallback
protected com.android.ex.photo.adapters.PhotoPagerAdapter
mAdapter
protected android.content.BroadcastReceiver
mInternetStateReceiver
protected com.android.ex.photo.views.PhotoView
mPhotoView
protected android.widget.ImageView
mPhotoPreviewImage
protected android.widget.TextView
mEmptyText
protected android.widget.ImageView
mRetryButton
protected com.android.ex.photo.views.ProgressBarWrapper
mPhotoProgressBar
protected int
mPosition
protected boolean
mFullScreen
Whether or not the fragment should make the photo full-screen
protected boolean
mWatchNetworkState
True if the PhotoViewFragment should watch the network state in order to restart loaders.
protected boolean
mOnlyShowSpinner
Whether or not this fragment will only show the loading spinner
protected boolean
mProgressBarNeeded
Whether or not the progress bar is showing valid information about the progress stated
protected android.view.View
mPhotoPreviewAndProgress
protected boolean
mThumbnailShown
protected boolean
mConnected
Whether or not there is currently a connection to the internet
protected boolean
mDisplayThumbsFullScreen
Whether or not we can display the thumbnail at fullscreen size
Constructors Summary
public PhotoViewFragment()
Public no-arg constructor for allowing the framework to handle orientation changes


                
      
        // Do nothing.
    
Methods Summary
private voidbindPhoto(android.graphics.drawable.Drawable drawable)
Binds an image to the photo view.

        if (drawable != null) {
            if (mPhotoView != null) {
                mPhotoView.bindDrawable(drawable);
            }
            enableImageTransforms(true);
            mPhotoPreviewAndProgress.setVisibility(View.GONE);
            mProgressBarNeeded = false;
        }
    
private voiddisplayPhoto(com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult result)

        if (result.status == BitmapResult.STATUS_EXCEPTION) {
            mProgressBarNeeded = false;
            mEmptyText.setText(R.string.failed);
            mEmptyText.setVisibility(View.VISIBLE);
            mCallback.onFragmentPhotoLoadComplete(this, false /* success */);
        } else {
            mEmptyText.setVisibility(View.GONE);
            final Drawable data = result.getDrawable(getResources());
            bindPhoto(data);
            mCallback.onFragmentPhotoLoadComplete(this, true /* success */);
        }
    
public voidenableImageTransforms(boolean enable)
Enable or disable image transformations. When transformations are enabled, this view consumes all touch events.

        mPhotoView.enableImageTransforms(enable);
    
protected com.android.ex.photo.PhotoViewCallbacksgetCallbacks()

        return ((ActivityInterface) getActivity()).getController();
    
public android.graphics.drawable.DrawablegetDrawable()

        return (mPhotoView != null ? mPhotoView.getDrawable() : null);
    
public android.widget.TextViewgetEmptyText()

        return mEmptyText;
    
public com.android.ex.photo.views.ProgressBarWrappergetPhotoProgressBar()

        return mPhotoProgressBar;
    
public java.lang.StringgetPhotoUri()

        return mResolvedPhotoUri;
    
public intgetPosition()

        return mPosition;
    
public android.widget.ImageViewgetRetryButton()

        return mRetryButton;
    
public static voidinitializeArguments(android.content.Intent intent, int position, boolean onlyShowSpinner, com.android.ex.photo.fragments.PhotoViewFragment f)

        final Bundle b = new Bundle();
        b.putParcelable(ARG_INTENT, intent);
        b.putInt(ARG_POSITION, position);
        b.putBoolean(ARG_SHOW_SPINNER, onlyShowSpinner);
        f.setArguments(b);
    
protected voidinitializeView(android.view.View view)

        mPhotoView = (PhotoView) view.findViewById(R.id.photo_view);
        mPhotoView.setMaxInitialScale(mIntent.getFloatExtra(Intents.EXTRA_MAX_INITIAL_SCALE, 1));
        mPhotoView.setOnClickListener(this);
        mPhotoView.setFullScreen(mFullScreen, false);
        mPhotoView.enableImageTransforms(false);

        mPhotoPreviewAndProgress = view.findViewById(R.id.photo_preview);
        mPhotoPreviewImage = (ImageView) view.findViewById(R.id.photo_preview_image);
        mThumbnailShown = false;
        final ProgressBar indeterminate =
                (ProgressBar) view.findViewById(R.id.indeterminate_progress);
        final ProgressBar determinate =
                (ProgressBar) view.findViewById(R.id.determinate_progress);
        mPhotoProgressBar = new ProgressBarWrapper(determinate, indeterminate, true);
        mEmptyText = (TextView) view.findViewById(R.id.empty_text);
        mRetryButton = (ImageView) view.findViewById(R.id.retry_button);

        // Don't call until we've setup the entire view
        setViewVisibility();
    
public booleanisPhotoBound()
Returns {@code true} if a photo has been bound. Otherwise, returns {@code false}.

        return (mPhotoView != null && mPhotoView.isPhotoBound());
    
public booleanisProgressBarNeeded()

        return mProgressBarNeeded;
    
public static com.android.ex.photo.fragments.PhotoViewFragmentnewInstance(android.content.Intent intent, int position, boolean onlyShowSpinner)
Create a {@link PhotoViewFragment}.

param
intent
param
position
param
onlyShowSpinner

        final PhotoViewFragment f = new PhotoViewFragment();
        initializeArguments(intent, position, onlyShowSpinner, f);
        return f;
    
public voidonActivityCreated(android.os.Bundle savedInstanceState)

        super.onActivityCreated(savedInstanceState);
        mCallback = getCallbacks();
        if (mCallback == null) {
            throw new IllegalArgumentException(
                    "Activity must be a derived class of PhotoViewActivity");
        }
        mAdapter = mCallback.getAdapter();
        if (mAdapter == null) {
            throw new IllegalStateException("Callback reported null adapter");
        }
        // Don't call until we've setup the entire view
        setViewVisibility();
    
public voidonClick(android.view.View v)

        mCallback.toggleFullScreen();
    
public voidonCreate(android.os.Bundle savedInstanceState)

        super.onCreate(savedInstanceState);

        final Bundle bundle = getArguments();
        if (bundle == null) {
            return;
        }
        mIntent = bundle.getParcelable(ARG_INTENT);
        mDisplayThumbsFullScreen = mIntent.getBooleanExtra(
                Intents.EXTRA_DISPLAY_THUMBS_FULLSCREEN, false);

        mPosition = bundle.getInt(ARG_POSITION);
        mOnlyShowSpinner = bundle.getBoolean(ARG_SHOW_SPINNER);
        mProgressBarNeeded = true;

        if (savedInstanceState != null) {
            final Bundle state = savedInstanceState.getBundle(STATE_INTENT_KEY);
            if (state != null) {
                mIntent = new Intent().putExtras(state);
            }
        }

        if (mIntent != null) {
            mResolvedPhotoUri = mIntent.getStringExtra(Intents.EXTRA_RESOLVED_PHOTO_URI);
            mThumbnailUri = mIntent.getStringExtra(Intents.EXTRA_THUMBNAIL_URI);
            mWatchNetworkState = mIntent.getBooleanExtra(Intents.EXTRA_WATCH_NETWORK, false);
        }
    
public android.support.v4.content.LoaderonCreateLoader(int id, android.os.Bundle args)

        if(mOnlyShowSpinner) {
            return null;
        }
        String uri = null;
        switch (id) {
            case PhotoViewCallbacks.BITMAP_LOADER_THUMBNAIL:
                uri = mThumbnailUri;
                break;
            case PhotoViewCallbacks.BITMAP_LOADER_PHOTO:
                uri = mResolvedPhotoUri;
                break;
        }
        return mCallback.onCreateBitmapLoader(id, args, uri);
    
public android.view.ViewonCreateView(android.view.LayoutInflater inflater, android.view.ViewGroup container, android.os.Bundle savedInstanceState)

        final View view = inflater.inflate(R.layout.photo_fragment_view, container, false);
        initializeView(view);
        return view;
    
public voidonCursorChanged(android.database.Cursor cursor)

        if (mAdapter == null) {
            // The adapter is set in onAttach(), and is guaranteed to be non-null. We have magically
            // received an onCursorChanged without attaching to an activity. Ignore this cursor
            // change.
            return;
        }
        // FLAG: There is a problem here:
        // If the cursor changes, and new items are added at an earlier position than
        // the current item, we will switch photos here. Really we should probably
        // try to find a photo with the same url and move the cursor to that position.
        if (cursor.moveToPosition(mPosition) && !isPhotoBound()) {
            mCallback.onCursorChanged(this, cursor);

            final LoaderManager manager = getLoaderManager();

            final Loader<BitmapResult> fakePhotoLoader = manager.getLoader(
                    PhotoViewCallbacks.BITMAP_LOADER_PHOTO);
            if (fakePhotoLoader != null) {
                final PhotoBitmapLoaderInterface loader = (PhotoBitmapLoaderInterface) fakePhotoLoader;
                mResolvedPhotoUri = mAdapter.getPhotoUri(cursor);
                loader.setPhotoUri(mResolvedPhotoUri);
                loader.forceLoad();
            }

            if (!mThumbnailShown) {
                final Loader<BitmapResult> fakeThumbnailLoader = manager.getLoader(
                        PhotoViewCallbacks.BITMAP_LOADER_THUMBNAIL);
                if (fakeThumbnailLoader != null) {
                    final PhotoBitmapLoaderInterface loader = (PhotoBitmapLoaderInterface) fakeThumbnailLoader;
                    mThumbnailUri = mAdapter.getThumbnailUri(cursor);
                    loader.setPhotoUri(mThumbnailUri);
                    loader.forceLoad();
                }
            }
        }
    
public voidonDestroyView()

        // Clean up views and other components
        if (mPhotoView != null) {
            mPhotoView.clear();
            mPhotoView = null;
        }
        super.onDestroyView();
    
public voidonDetach()

        mCallback = null;
        super.onDetach();
    
public voidonFullScreenChanged(boolean fullScreen)

        setViewVisibility();
    
public booleanonInterceptMoveLeft(float origX, float origY)

        if (!mCallback.isFragmentActive(this)) {
            // we're not in the foreground; don't intercept any touches
            return false;
        }

        return (mPhotoView != null && mPhotoView.interceptMoveLeft(origX, origY));
    
public booleanonInterceptMoveRight(float origX, float origY)

        if (!mCallback.isFragmentActive(this)) {
            // we're not in the foreground; don't intercept any touches
            return false;
        }

        return (mPhotoView != null && mPhotoView.interceptMoveRight(origX, origY));
    
public voidonLoadFinished(android.support.v4.content.Loader loader, com.android.ex.photo.loaders.PhotoBitmapLoaderInterface.BitmapResult result)

        // If we don't have a view, the fragment has been paused. We'll get the cursor again later.
        // If we're not added, the fragment has detached during the loading process. We no longer
        // need the result.
        if (getView() == null || !isAdded()) {
            return;
        }

        final Drawable data = result.getDrawable(getResources());

        final int id = loader.getId();
        switch (id) {
            case PhotoViewCallbacks.BITMAP_LOADER_THUMBNAIL:
                if (mDisplayThumbsFullScreen) {
                    displayPhoto(result);
                } else {
                    if (isPhotoBound()) {
                        // There is need to do anything with the thumbnail
                        // image, as the full size image is being shown.
                        return;
                    }

                    if (data == null) {
                        // no preview, show default
                        mPhotoPreviewImage.setImageResource(R.drawable.default_image);
                        mThumbnailShown = false;
                    } else {
                        // show preview
                        mPhotoPreviewImage.setImageDrawable(data);
                        mThumbnailShown = true;
                    }
                    mPhotoPreviewImage.setVisibility(View.VISIBLE);
                    if (getResources().getBoolean(R.bool.force_thumbnail_no_scaling)) {
                        mPhotoPreviewImage.setScaleType(ImageView.ScaleType.CENTER);
                    }
                    enableImageTransforms(false);
                }
                break;

            case PhotoViewCallbacks.BITMAP_LOADER_PHOTO:
                displayPhoto(result);
                break;
            default:
                break;
        }

        if (mProgressBarNeeded == false) {
            // Hide the progress bar as it isn't needed anymore.
            mPhotoProgressBar.setVisibility(View.GONE);
        }

        if (data != null) {
            mCallback.onNewPhotoLoaded(mPosition);
        }
        setViewVisibility();
    
public voidonLoaderReset(android.support.v4.content.Loader loader)

        // Do nothing
    
public voidonPause()

        // Remove listeners
        if (mWatchNetworkState) {
            getActivity().unregisterReceiver(mInternetStateReceiver);
        }
        mCallback.removeCursorListener(this);
        mCallback.removeScreenListener(mPosition);
        resetPhotoView();
        super.onPause();
    
public voidonResume()

        super.onResume();
        mCallback.addScreenListener(mPosition, this);
        mCallback.addCursorListener(this);

        if (mWatchNetworkState) {
            if (mInternetStateReceiver == null) {
                mInternetStateReceiver = new InternetStateBroadcastReceiver();
            }
            getActivity().registerReceiver(mInternetStateReceiver,
                    new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetInfo != null) {
                mConnected = activeNetInfo.isConnected();
            } else {
                // Best to set this to false, since it won't stop us from trying to download,
                // only allow us to try re-download if we get notified that we do have a connection.
                mConnected = false;
            }
        }

        if (!isPhotoBound()) {
            mProgressBarNeeded = true;
            mPhotoPreviewAndProgress.setVisibility(View.VISIBLE);

            getLoaderManager().initLoader(PhotoViewCallbacks.BITMAP_LOADER_THUMBNAIL,
                    null, this);

            // FLAG: If we are displaying thumbnails at fullscreen size, then we
            // could defer the loading of the fullscreen image until the thumbnail
            // has finished loading, or even until the user attempts to zoom in.
            getLoaderManager().initLoader(PhotoViewCallbacks.BITMAP_LOADER_PHOTO,
                    null, this);
        }
    
public voidonSaveInstanceState(android.os.Bundle outState)

        super.onSaveInstanceState(outState);

        if (mIntent != null) {
            outState.putParcelable(STATE_INTENT_KEY, mIntent.getExtras());
        }
    
public voidonViewActivated()

        if (!mCallback.isFragmentActive(this)) {
            // we're not in the foreground; reset our view
            resetViews();
        } else {
            if (!isPhotoBound()) {
                // Restart the loader
                getLoaderManager().restartLoader(PhotoViewCallbacks.BITMAP_LOADER_THUMBNAIL,
                        null, this);
            }
            mCallback.onFragmentVisible(this);
        }
    
public voidonViewUpNext()

        resetViews();
    
private voidresetPhotoView()
Resets the photo view to it's default state w/ no bound photo.

        if (mPhotoView != null) {
            mPhotoView.bindPhoto(null);
        }
    
public voidresetViews()
Reset the views to their default states

        if (mPhotoView != null) {
            mPhotoView.resetTransformations();
        }
    
public voidsetFullScreen(boolean fullScreen)
Sets full-screen mode for the views.

        mFullScreen = fullScreen;
    
private voidsetViewVisibility()
Sets view visibility depending upon whether or not we're in "full screen" mode.

        final boolean fullScreen = mCallback == null ? false : mCallback.isFragmentFullScreen(this);
        setFullScreen(fullScreen);