Android Open Source - Patio Patio






From Project

Back to project page Patio.

License

The source code is released under:

MIT License

If you think the Android project Patio listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.andressantibanez.android.patio;
/*  ww  w. j a v  a2 s . c  o m*/
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.easyandroidanimations.library.Animation;
import com.easyandroidanimations.library.SlideInAnimation;
import com.easyandroidanimations.library.SlideOutAnimation;
import com.squareup.picasso.Picasso;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class Patio extends LinearLayout implements View.OnClickListener {

    /**
     * Constants
     */
    public final static String TAG = Patio.class.getSimpleName();
    public final static int DEFAULT_MAX_PICTURES = 3;

    /**
     * Variables
     */
    private final int WIDGET_LAYOUT_RES_ID = R.layout.patio_layout;
    private final int THUMBNAIL_LAYOUT_RES_ID = R.layout.patio_thumbnail;
    private Context mContext;
    private int mMaxPictures;
    private PatioCallbacks mListener;
    private ArrayList<PatioThumbnail> mPatioThumbnails;
    private String mTakePicturePath;

    //Resources
    private float mThumbnailWidth;
    private float mThumbnailHeight;
    private String mThumbnailsMessageString;

    /**
     * Controls
     */
    //Actions
    public Button mTakePicture;
    public Button mAttachPicture;
    public Button mRemovePicture;
    public Button mCancel;
    //Containers
    public HorizontalScrollView mThumbnailsWrapper;
    public LinearLayout mThumbnailsContainer;
    public TextView mThumbnailsCount;
    //Toolbars
    public LinearLayout mToolbarAddActions;
    public LinearLayout mToolbarRemoveActions;

    //TODO: http://ryanharter.com/blog/2014/08/29/building-dynamic-custom-views/

    /**
     * Constructor
     */
    public Patio(Context context) {
        super(context);
        init(context, null);
    }

    public Patio(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public Patio(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    /**
     * Lifecycle methods
     * https://speakerdeck.com/cyrilmottier/deep-dive-into-android-state-restoration
     * https://github.com/CharlesHarley/Example-Android-SavingInstanceState/blob/master/src/com/example/android/savinginstancestate/views/LockCombinationPicker.java
     * https://gist.github.com/granoeste/4037468
     */
    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();

        SavedState savedState = new SavedState(superState);
        savedState.setThumbnailsPaths(getThumbnailsPaths());
        savedState.setTakePicturePath(mTakePicturePath);

        return savedState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState) state;
        super.onRestoreInstanceState(savedState.getSuperState());

        ArrayList<String> thumbnailsPaths = savedState.getThumbnailsPaths();
        String takePicturePath = savedState.getTakePicturePath();

        restoreState(thumbnailsPaths, takePicturePath);
    }

    /**
     * Custom methods
     */
    public void init(Context context, AttributeSet attributeSet) {
        //Setup defaults
        mContext = context;
        mMaxPictures = DEFAULT_MAX_PICTURES;
        mThumbnailHeight = mContext.getResources().getDimension(R.dimen.patio_default_thumbnail_height);
        mThumbnailWidth = mContext.getResources().getDimension(R.dimen.patio_default_thumbnail_width);
        mThumbnailsMessageString = mContext.getResources().getString(R.string.patio_thumbnails_message);
        mPatioThumbnails = new ArrayList<PatioThumbnail>();
        setOrientation(VERTICAL);

        //Local defaults
        float thumbnailsContainerPadding = mContext.getResources().getDimension(R.dimen.patio_default_thumbnails_container_padding);
        int actionsTextColor = mContext.getResources().getColor(R.color.patio_default_action_text_color);
        int thumbnailsWrapperBackground = mContext.getResources().getColor(R.color.patio_default_thumbnails_container_background);


        //Inflate view and setup controls
        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(WIDGET_LAYOUT_RES_ID, this, true);
        //Buttons
        mTakePicture = (Button) findViewById(R.id.patio_action_take_picture);
        mAttachPicture = (Button) findViewById(R.id.patio_action_attach_picture);
        mRemovePicture = (Button) findViewById(R.id.patio_action_remove_picture);
        mCancel = (Button) findViewById(R.id.patio_action_cancel);
        //Containers
        mThumbnailsWrapper = (HorizontalScrollView) findViewById(R.id.patio_thumbnails_wrapper);
        mThumbnailsContainer = (LinearLayout) findViewById(R.id.patio_thumbnails_container);
        mThumbnailsCount = (TextView) findViewById(R.id.patio_thumbnails_count_message);
        //Toolbars
        mToolbarAddActions = (LinearLayout) findViewById(R.id.patio_add_actions_toolbar);
        mToolbarRemoveActions = (LinearLayout) findViewById(R.id.patio_remove_actions_toolbar);
        mToolbarRemoveActions.setVisibility(View.GONE);

        //Set actions listeners
        if(!isInEditMode()) {
            mTakePicture.setOnClickListener(this);
            mAttachPicture.setOnClickListener(this);
            mRemovePicture.setOnClickListener(this);
            mCancel.setOnClickListener(this);
        }

        //Get defined attributes
        if(attributeSet != null) {
            TypedArray a = mContext.getTheme().obtainStyledAttributes(attributeSet, R.styleable.Patio, 0, 0);
            try {
                //Runtime
                mMaxPictures = a.getInt(R.styleable.Patio_maxPictures, DEFAULT_MAX_PICTURES);
                mThumbnailHeight = a.getDimension(R.styleable.Patio_thumbnailHeight, mThumbnailHeight);
                mThumbnailWidth = a.getDimension(R.styleable.Patio_thumbnailWidth, mThumbnailWidth);
                mThumbnailsMessageString = a.getString(R.styleable.Patio_thumbnailsMessage);
                //Local
                thumbnailsContainerPadding = a.getDimension(R.styleable.Patio_thumbnailsContainerPadding, thumbnailsContainerPadding);
                actionsTextColor = a.getColor(R.styleable.Patio_actionsTextColor, actionsTextColor);
                thumbnailsWrapperBackground = a.getColor(R.styleable.Patio_thumbnailsContainerBackground, thumbnailsWrapperBackground);
            } finally {
                a.recycle();
            }
        }

        //Check Max Pictures
        if(mMaxPictures <= 0) {
            mMaxPictures = DEFAULT_MAX_PICTURES;
        }

        //Check Thumbnail Message
        if(mThumbnailsMessageString == null) {
            mThumbnailsMessageString = mContext.getResources().getString(R.string.patio_thumbnails_message);
        }

        //Setup actions text color
        mTakePicture.setTextColor(actionsTextColor);
        mAttachPicture.setTextColor(actionsTextColor);
        mRemovePicture.setTextColor(actionsTextColor);
        mCancel.setTextColor(actionsTextColor);

        //Setup thumbnails container background
        mThumbnailsWrapper.setBackgroundColor(thumbnailsWrapperBackground);

        //Setup dimensions
        ViewGroup.LayoutParams layoutParams;
        int paddingTop, paddingBottom, paddingLeft, paddingRight;
        //Thumbnails Wrapper height
        layoutParams = mThumbnailsWrapper.getLayoutParams();
        layoutParams.height = Float.valueOf(mThumbnailHeight).intValue();
        mThumbnailsWrapper.setLayoutParams(layoutParams);
        //Thumbnails Container padding
        paddingTop = paddingBottom = paddingLeft = paddingRight = Float.valueOf(thumbnailsContainerPadding).intValue();
        mThumbnailsContainer.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);

        //Init Thumbnails Message
        updateThumbnailsMessage();
    }

    public void restoreState(ArrayList<String> thumbnailsPaths, String takePicturePath) {
        for(String thumbnailPath : thumbnailsPaths) {
            addThumbnail(thumbnailPath);
        }
        mTakePicturePath = takePicturePath;
    }

    public void addThumbnail(String thumbnailPath) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        ImageView imageView = (ImageView) inflater.inflate(THUMBNAIL_LAYOUT_RES_ID, mThumbnailsContainer, false);

        int resizeDimension = mThumbnailWidth > mThumbnailHeight ?
                Float.valueOf(mThumbnailWidth).intValue() :
                Float.valueOf(mThumbnailHeight).intValue();
        Picasso.with(mContext)
                .load(new File(thumbnailPath))
                .resize(resizeDimension, resizeDimension)
                .centerCrop()
                .into(imageView);

        ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
        layoutParams.width = Float.valueOf(mThumbnailWidth).intValue();
        layoutParams.height = Float.valueOf(mThumbnailHeight).intValue();
        mThumbnailsContainer.addView(imageView, 0, layoutParams);
        imageView.setOnClickListener(this);

        mPatioThumbnails.add(new PatioThumbnail(thumbnailPath, imageView));
        updateThumbnailsMessage();
    }

    public void updateThumbnailsMessage() {
        int count = mPatioThumbnails.size();
        Resources res = mContext.getResources();
        String thumbnailsCountMessage = String.format(mThumbnailsMessageString, count, mMaxPictures);
        mThumbnailsCount.setText(thumbnailsCountMessage);

        //Check actions button if max pictures reached
        boolean actionsEnabled = mPatioThumbnails.size() < mMaxPictures;
        mTakePicture.setEnabled(actionsEnabled);
        mAttachPicture.setEnabled(actionsEnabled);
    }

    public void setCallbacksListener(PatioCallbacks listener) {
        mListener = listener;
    }

    public Intent getTakePictureIntent() {
        mTakePicturePath = null;
        File pictureFile = null;
        try {
            pictureFile = PatioUtils.getNewImageFile();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        if(pictureFile == null)
            return null;

        mTakePicturePath = pictureFile.getAbsolutePath();
        Log.d(TAG, "Path: " + mTakePicturePath);

        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pictureFile));
        return takePictureIntent;
    }

    public Intent getAttachPictureIntent() {
        Intent attachPictureIntent = new Intent(Intent.ACTION_PICK);
        attachPictureIntent.setType("image/*");
        return attachPictureIntent;
    }

    public void handleTakePictureResult(Intent data) {
        Log.d(TAG, "File Path: " + mTakePicturePath);

        addThumbnail(mTakePicturePath);
        PatioUtils.addNewImageToGallery(mContext, mTakePicturePath);
    }

    public void handleAttachPictureResult(Intent data) {
        Uri uri = data.getData();
        String filePath = PatioUtils.getRealPathFromURI(mContext, uri);
        Log.d(TAG, "File Path: " + filePath);

        addThumbnail(filePath);
    }

    public void showAddToolbar() {
        if(mToolbarAddActions.getVisibility() == View.VISIBLE)
            return;

        new SlideOutAnimation(mToolbarRemoveActions).setDirection(Animation.DIRECTION_UP).animate();
        new SlideInAnimation(mToolbarAddActions).setDirection(Animation.DIRECTION_UP).animate();
    }

    public void showRemoveToolbar() {
        if(mToolbarRemoveActions.getVisibility() == View.VISIBLE)
            return;

        new SlideOutAnimation(mToolbarAddActions).setDirection(Animation.DIRECTION_UP).animate();
        new SlideInAnimation(mToolbarRemoveActions).setDirection(Animation.DIRECTION_UP).animate();
    }

    public void cancelThumbnailSelection() {
        for(PatioThumbnail patioThumbnail : mPatioThumbnails) {
            patioThumbnail.setSelected(false);
        }
        checkToolbarsStatus();
    }

    public void removeSelectedThumbnails() {
        for(int i = mPatioThumbnails.size() - 1; i >= 0; i--) {
            if(mPatioThumbnails.get(i).isSelected()) {
                ImageView thumbnailView = mPatioThumbnails.get(i).getThumbnailView();
                mThumbnailsContainer.removeView(thumbnailView);
                mPatioThumbnails.remove(i);
            }
        }
        updateThumbnailsMessage();
        checkToolbarsStatus();
    }

    public void checkToolbarsStatus() {
        boolean thumbnailsSelected = false;
        for(PatioThumbnail patioThumbnail : mPatioThumbnails) {
            if (patioThumbnail.getThumbnailView().getAlpha() == 0.5f) {
                thumbnailsSelected = true;
                break;
            }
        }

        if(thumbnailsSelected)
            showRemoveToolbar();
        else
            showAddToolbar();
    }

    public ArrayList<String> getThumbnailsPaths() {
        ArrayList<String> thumbnailsPaths = new ArrayList<String>();
        for(PatioThumbnail patioThumbnail : mPatioThumbnails) {
            thumbnailsPaths.add(patioThumbnail.getThumbnailPath());
        }
        return thumbnailsPaths;
    }

    /**
     * OnClick buttons methods
     */
    @Override
    public void onClick(View view) {
        //Buttons
        if(view instanceof Button) {
            if(view.getId() == R.id.patio_action_take_picture) {
                mListener.onTakePictureClick();
            }
            if(view.getId() == R.id.patio_action_attach_picture) {
                mListener.onAddPictureClick();
            }
            if(view.getId() == R.id.patio_action_remove_picture) {
                removeSelectedThumbnails();
            }
            if(view.getId() == R.id.patio_action_cancel) {
                cancelThumbnailSelection();
            }
        }

        //Thumbnails
        if(view instanceof ImageView) {
            //Check for PatioThumbnail
            for(PatioThumbnail patioThumbnail : mPatioThumbnails) {
                //Inverse selection for selected thumbnail
                if(patioThumbnail.getThumbnailView().equals(view)) {
                    patioThumbnail.setSelected(!patioThumbnail.isSelected());
                    break;
                }
            }
            checkToolbarsStatus();
        }
    }

    /**
     * Interface
     */
    public interface PatioCallbacks {
        public void onTakePictureClick();
        public void onAddPictureClick();
    }

    /**
     * SavedState class for restoring view state
     */
    protected static class SavedState extends BaseSavedState {
        public ArrayList<String> mThumbnailsPaths;
        private String mTakePictureFilePath;

        public SavedState(Parcelable superState) {
            super(superState);
        }

        public SavedState(Parcel in) {
            super(in);
            mThumbnailsPaths = in.readArrayList(String.class.getClassLoader());
            mTakePictureFilePath = in.readString();
        }

        @Override
        public void writeToParcel(Parcel out, int flags) {
            super.writeToParcel(out, flags);
            out.writeList(mThumbnailsPaths);
            out.writeString(mTakePictureFilePath);
        }

        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };

        public void setThumbnailsPaths(ArrayList<String> thumbnailsPaths) {
            mThumbnailsPaths = thumbnailsPaths;
        }
        public ArrayList<String> getThumbnailsPaths() {
            return mThumbnailsPaths;
        }

        public void setTakePicturePath(String takePictureFilePath) {
            mTakePictureFilePath = takePictureFilePath;
        }

        public String getTakePicturePath() {
            return mTakePictureFilePath;
        }

    }
}




Java Source Code List

com.andressantibanez.android.patio.ApplicationTest.java
com.andressantibanez.android.patio.PatioThumbnail.java
com.andressantibanez.android.patio.PatioUtils.java
com.andressantibanez.android.patio.Patio.java
com.asantibanez.android.patiodemo.ApplicationTest.java
com.asantibanez.android.patiodemo.MainActivity.java