com.andremion.louvre.preview.PreviewAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.andremion.louvre.preview.PreviewAdapter.java

Source

/*
 * Copyright (c) 2017. Andr Mion
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.andremion.louvre.preview;

import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckedTextView;
import android.widget.ImageView;

import com.andremion.louvre.R;
import com.andremion.louvre.util.transition.MediaSharedElementCallback;
import com.squareup.picasso.Callback;
import com.squareup.picasso.MemoryPolicy;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;

import static android.view.View.NO_ID;

class PreviewAdapter extends PagerAdapter {

    interface Callbacks {

        void onCheckedUpdated(boolean checked);

        void onMaxSelectionReached();
    }

    private final FragmentActivity mActivity;
    private final LayoutInflater mInflater;
    private final CheckedTextView mCheckbox;
    private final MediaSharedElementCallback mSharedElementCallback;
    private final HashMap<Long, Uri> mSelection;
    @Nullable
    private PreviewAdapter.Callbacks mCallbacks;
    private int mMaxSelection;
    private int mInitialPosition;
    @Nullable
    private Cursor mData;
    private boolean mDontAnimate;
    private int mCurrentPosition = RecyclerView.NO_POSITION;

    PreviewAdapter(@NonNull FragmentActivity activity, @NonNull CheckedTextView checkbox,
            @NonNull MediaSharedElementCallback sharedElementCallback, @NonNull HashMap<Long, Uri> selection) {
        mActivity = activity;
        mInflater = LayoutInflater.from(activity);
        mCheckbox = checkbox;
        mSharedElementCallback = sharedElementCallback;
        mSelection = selection;
        mDontAnimate = true;
    }

    void setCallbacks(@Nullable PreviewAdapter.Callbacks callbacks) {
        mCallbacks = callbacks;
    }

    void setMaxSelection(@IntRange(from = 0) int maxSelection) {
        mMaxSelection = maxSelection;
    }

    void setInitialPosition(int position) {
        mInitialPosition = position;
    }

    void swapData(Cursor data) {
        if (data != mData) {
            mData = data;
            notifyDataSetChanged();
        }
    }

    void setDontAnimate(boolean dontAnimate) {
        mDontAnimate = dontAnimate;
    }

    @Override
    public int getCount() {
        if (mData != null && !mData.isClosed()) {
            return mData.getCount();
        }
        return 0;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = mInflater.inflate(R.layout.page_item_preview, container, false);
        ViewHolder holder = new ViewHolder(view);
        Uri data = getData(position);
        onViewBound(holder, position, data);
        container.addView(holder.itemView);
        return holder;
    }

    @Nullable
    Uri getData(int position) {
        if (mData != null && !mData.isClosed()) {
            mData.moveToPosition(position);
            return Uri.fromFile(new File(mData.getString(mData.getColumnIndex(MediaStore.Images.Media.DATA))));
        }
        return null;
    }

    private long getItemId(int position) {
        if (mData != null && !mData.isClosed()) {
            mData.moveToPosition(position);
            return mData.getLong(mData.getColumnIndex(MediaStore.Images.ImageColumns._ID));
        }
        return NO_ID;
    }

    private void onViewBound(ViewHolder holder, int position, Uri data) {
        String imageTransitionName = holder.imageView.getContext()
                .getString(R.string.activity_gallery_image_transition, data.toString());
        ViewCompat.setTransitionName(holder.imageView, imageTransitionName);
        RequestCreator request = Picasso.with(mActivity).load(data)
                .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).fit().centerInside();
        if (mDontAnimate) {
            request.noFade();
        }
        request.into(holder.imageView, new ImageLoadingCallback(position));
    }

    private boolean isSelected(int position) {
        long itemId = getItemId(position);
        return mSelection.containsKey(itemId);
    }

    private void startPostponedEnterTransition(int position) {
        if (position == mInitialPosition) {
            mActivity.supportStartPostponedEnterTransition();
        }
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        if (object instanceof ViewHolder) {
            mCurrentPosition = position;
            mSharedElementCallback.setSharedElementViews(((ViewHolder) object).imageView, mCheckbox);
            if (mCallbacks != null) {
                mCallbacks.onCheckedUpdated(isSelected(position));
            }
        }
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return object instanceof ViewHolder && view.equals(((ViewHolder) object).itemView);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        View view = ((ViewHolder) object).itemView;
        container.removeView(view);
    }

    void selectCurrentItem() {
        boolean selectionChanged = handleChangeSelection(mCurrentPosition);
        if (selectionChanged) {
            notifyDataSetChanged();
        }
        if (mCallbacks != null) {
            if (selectionChanged) {
                mCallbacks.onCheckedUpdated(isSelected(mCurrentPosition));
            } else {
                mCallbacks.onMaxSelectionReached();
            }
        }
    }

    LinkedHashMap<Long, Uri> getRawSelection() {
        return new LinkedHashMap<>(mSelection);
    }

    private boolean handleChangeSelection(int position) {
        final long itemId = getItemId(position);
        if (!isSelected(position)) {
            if (mSelection.size() == mMaxSelection) {
                return false;
            }
            mSelection.put(itemId, getData(position));
        } else {
            mSelection.remove(itemId);
        }
        return true;
    }

    private static class ViewHolder {

        final View itemView;
        final ImageView imageView;

        ViewHolder(View view) {
            itemView = view;
            imageView = (ImageView) view.findViewById(R.id.image);
        }

    }

    private class ImageLoadingCallback implements Callback {

        final int mPosition;

        ImageLoadingCallback(int position) {
            mPosition = position;
        }

        @Override
        public void onSuccess() {
            startPostponedEnterTransition(mPosition);
        }

        @Override
        public void onError() {
            startPostponedEnterTransition(mPosition);
        }

    }

}