Divya
Divya

Reputation: 543

Instagram like scroll in custom gallery

Can anyone please suggest how to implement the following in my droid app? I've created a custom gallery, and when an image is selected, I show a preview of the image exactly like instagram. Now when I scoll up, I need some 20% of the image view to stick to the top like this: enter image description here

I'm right now using, Observablegrid view, which is of not that much use!

Please suggest any ideas. Thanks!

Upvotes: 7

Views: 3010

Answers (2)

Nitesh Rathod
Nitesh Rathod

Reputation: 366

<?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="wrap_content"
    android:orientation="vertical"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_below="@+id/mainFrame">

 <RelativeLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RelativeLayout
            android:id="@+id/gallery_lay"
            android:layout_width="wrap_content"
            android:layout_height="365dp"
            android:background="@color/black"
            android:orientation="vertical">


            <com.fenchtose.nocropper.CropperView
                android:id="@+id/imageview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#ff282828"
                app:nocropper__grid_color="@color/colorAccent"
                app:nocropper__grid_opacity="0.8"
                app:nocropper__grid_thickness="0.8dp"
                app:nocropper__padding_color="@color/colorAccent" />

 </RelativeLayout>
    </RelativeLayout>

    <com.myapp.Util.ObservableGridView
        android:id="@+id/camera_gridView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:numColumns="4" />

</FrameLayout>

And below is java implementation

public class GalleryFragmentTest2 extends Fragment implements View.OnClickListener, ImageGridItemListner, ObservableScrollViewCallbacks {
    private static final String TAG = "GalleryFragment";

    CropperView mImageView;
    RecyclerView recImgHolder;
    CoordinatorLayout container;
    AppBarLayout app_bar_main;
    private Bitmap originalBitmap;
    private Bitmap mBitmap;
    private boolean isSnappedToCenter = false;

    private int rotationCount = 0;

    //constants
    private static final int NUM_GRID_COLUMNS = 4;


    //widgets
    private GridView gridView;
    private ImageView galleryImage;
    private Spinner directorySpinner;

    //vars
    private ArrayList<Model_images> directories;
    private String mAppend = "file://";
    private String mSelectedImage;
    RelativeLayout mHeaderView, relCropperView;
    ObservableGridView camera_gridView;

    private int mBaseTranslationY;

    private void initImageLoader() {
        UniversalImageLoader universalImageLoader = new UniversalImageLoader(getContext());
        ImageLoader.getInstance().init(universalImageLoader.getConfig());
    }

    @SuppressLint("ClickableViewAccessibility")
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.gallery_test2, container, false);


        mHeaderView = (RelativeLayout) view.findViewById(R.id.header);
        View mToolbarView = view.findViewById(R.id.toolbar);
        camera_gridView = (ObservableGridView) view.findViewById(R.id.camera_gridView);

        LayoutInflater inflaters = LayoutInflater.from(getActivity());
        View view1 = inflaters.inflate(R.layout.snippet_top_gallerytoolbar,camera_gridView,false);
        View view2 = inflaters.inflate(R.layout.rec_img_test,camera_gridView,false);

        camera_gridView.addHeaderView(inflaters.inflate(R.layout.snippet_top_gallerytoolbar,camera_gridView,false));
// view that leaves 300dp space to display the selected image from the grid
        camera_gridView.addHeaderView(inflaters.inflate(R.layout.rec_img_test,camera_gridView,false));
// a sticky view with action bar's height, so that the grid doesn't scroll above this

        camera_gridView.setScrollViewCallbacks(this);

        mImageView = (CropperView) view.findViewById(R.id.imageview);
        recImgHolder = view2.findViewById(R.id.recImgHolder);

        LinearLayoutManager manager = new GridLayoutManager(getActivity(), 4);
        recImgHolder.setLayoutManager(manager);
        recImgHolder.setHasFixedSize(true);
        recImgHolder.setItemViewCacheSize(20);
        recImgHolder.setDrawingCacheEnabled(true);
        recImgHolder.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

        TextView nextScreen = (TextView) view.findViewById(R.id.tvNext);

        directorySpinner = (Spinner) view1.findViewById(R.id.spinnerDirectory);

        directories = new ArrayList<>();
        Log.d(TAG, "onCreateView: started.");

        initImageLoader();
        init();


        mImageView.setDebug(true);
        mImageView.setGestureEnabled(true);

        mImageView.setGridCallback(new CropperView.GridCallback() {
            @Override
            public boolean onGestureStarted() {
                return true;
            }

            @Override
            public boolean onGestureCompleted() {
                return false;
            }
        });




        return view;
    }



    private void init() {

        try {

            FilePaths filePaths = new FilePaths();
            directories = new ArrayList<>();
            //check for other folders indide "/storage/emulated/0/pictures"
            directories = FileSearch.fn_imagespath(Objects.requireNonNull(getContext()), filePaths.PICTURES);

            ArrayList<String> directoryNames = new ArrayList<>();
            for (int i = 0; i < directories.size(); i++) {
                int index = directories.get(i).getStr_folder().lastIndexOf("/");
                String string = directories.get(i).getStr_folder().substring(index + 1);
                directoryNames.add(string);
            }

            ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
                    android.R.layout.simple_spinner_item, directoryNames);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

            directorySpinner.setAdapter(adapter);

            directorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    Log.d(TAG, "onItemClick: selected: " + directories.get(position));

                    //setup our image grid for the directory chosen
                    setupGridView(directories.get(position));
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private void setupGridView(Model_images selectedDirectory) {

        try {
            final ArrayList<String> imgURLs = selectedDirectory.getAl_imagepath();

            //use the grid adapter to adapter the images to gridview
            GridImageAdapter adapter = new GridImageAdapter(getActivity(), R.layout.layout_grid_imageview, mAppend, imgURLs, (ImageGridItemListner) this);
            adapter.setGridItemListner(this);

            recImgHolder.setAdapter(adapter);

            //set the first image to be displayed when the activity fragment view is inflated
            try {
                setImage(imgURLs.get(0), mAppend);
            } catch (ArrayIndexOutOfBoundsException e) {
                Log.e(TAG, "setupGridView: ArrayIndexOutOfBoundsException: " + e.getMessage());
            }
        }catch (Exception e){
            e.printStackTrace();
            Toast.makeText(getActivity(), ""+e.getMessage(), Toast.LENGTH_SHORT).show();
        }



    }


    private void setImage(String imgURL, String append) {
        Log.d(TAG, "setImage: setting image");

        ImageLoader imageLoader = ImageLoader.getInstance();
        Bitmap bmp = imageLoader.loadImageSync(append + imgURL);
        mImageView.setImageBitmap(bmp);
        mBitmap = bmp;
        originalBitmap = bmp;


    }

    private void rotateImage() {
        if (mBitmap == null) {
            Log.e(TAG, "bitmap is not loaded yet");
            return;
        }

        mBitmap = BitmapUtils.rotateBitmap(mBitmap, 90);
        mImageView.setImageBitmap(mBitmap);
        rotationCount++;
    }

    private void snapImage() {
        if (isSnappedToCenter) {
            mImageView.cropToCenter();
        } else {
            mImageView.fitToCenter();
        }

        isSnappedToCenter = !isSnappedToCenter;
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.rotate_button:
                rotateImage();
                break;
            case R.id.snap_button:
                snapImage();
                break;
        }
    }

    @Override
    public void onImageGridItemClick(String imgURL) {
        try {
            setImage(imgURL, mAppend);
        } catch (ArrayIndexOutOfBoundsException e) {
            Log.e(TAG, "setupGridView: ArrayIndexOutOfBoundsException: " + e.getMessage());
        }
    }

    //overridden methods

    @Override
    public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
        if (dragging) {
            int toolbarHeight = mHeaderView.getHeight();
            //    int toolbarHeight = 300;
            if (camera_gridView.getCurrentScrollY() == 0) {
                showToolbar();

            }
            if (firstScroll) {

                float currentHeaderTranslationY = ViewHelper.getTranslationY(mHeaderView);
                if (-toolbarHeight < currentHeaderTranslationY) {
                    mBaseTranslationY = scrollY;
                }
            }
            float headerTranslationY = ScrollUtils.getFloat(-(scrollY - mBaseTranslationY), -toolbarHeight, 0);
            ViewPropertyAnimator.animate(mHeaderView).cancel();
            ViewHelper.setTranslationY(mHeaderView, headerTranslationY);
        }
    }

    @Override
    public void onDownMotionEvent() {

    }

    @Override
    public void onUpOrCancelMotionEvent(ScrollState scrollState) {
        mBaseTranslationY = 0;

        if (scrollState == ScrollState.DOWN) {
            int toolbarHeight = mHeaderView.getHeight();
            if (camera_gridView.getCurrentScrollY() == 0) {
                showToolbar();

            }
            int scrollY = camera_gridView.getCurrentScrollY();
            if (toolbarHeight <= scrollY) {
                hideToolbar();

            } else {
                showToolbar();
            }

        } else if (scrollState == ScrollState.UP) {
            int toolbarHeight = mHeaderView.getHeight();
            int scrollY = camera_gridView.getCurrentScrollY();
            if (toolbarHeight <= scrollY) {
                System.out.println("++++upif" + scrollY);
                hideToolbar();
            } else {
                System.out.println("++++upelse" + scrollY);
                showToolbar();
            }
            if (camera_gridView.getCurrentScrollY() == 0) {
                showToolbar();
            }
        } else {
            if (!toolbarIsShown() && !toolbarIsHidden()) {
                showToolbar();
            }
        }
    }

    //method to show the toolbar
    private void showToolbar() {
        float headerTranslationY = ViewHelper.getTranslationY(mHeaderView);
        if (headerTranslationY != 0) {
            ViewPropertyAnimator.animate(mHeaderView).cancel();
            ViewPropertyAnimator.animate(mHeaderView).translationY(0).setDuration(200).start();
        }
    }

    //method to hide the toolbar
    private void hideToolbar() {
        float headerTranslationY = ViewHelper.getTranslationY(mHeaderView);
        int toolbarHeight = mHeaderView.getHeight();
        if (headerTranslationY != -toolbarHeight) {
            ViewPropertyAnimator.animate(mHeaderView).cancel();
            ViewPropertyAnimator.animate(mHeaderView).translationY(-toolbarHeight).setDuration(200).start();
        }
    }

    private boolean toolbarIsShown() {
        return ViewHelper.getTranslationY(mHeaderView) == 0;
    }

    private boolean toolbarIsHidden() {
        return ViewHelper.getTranslationY(mHeaderView) == -mHeaderView.getHeight();
    }
}

inflated headerview in observable is

layout :- snippet_top_gallerytoolbar

<android.support.design.widget.AppBarLayout android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="@color/colorPrimary"
    xmlns:android="http://schemas.android.com/apk/res/android">

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

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <ImageView
                    android:id="@+id/ivCloseShare"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_centerVertical="true"
                    android:layout_marginEnd="20dp"
                    android:src="@drawable/ic_back" />

                <Spinner
                    android:id="@+id/spinnerDirectory"
                    android:layout_width="@dimen/_120sdp"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_toRightOf="@+id/ivCloseShare"
                    android:gravity="center_vertical"
                    android:text="Gallery"
                    android:textColor="@color/black"
                    android:textSize="20sp">


                </Spinner>

                <TextView
                    android:id="@+id/tvNext"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:layout_marginRight="15dp"
                    android:text="@string/string_next"
                    android:textColor="@color/white"
                    android:textSize="20sp" />


            </RelativeLayout>


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


    </android.support.design.widget.AppBarLayout>

second added headerview to observablegrid

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recImgHolder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

i am getting view like below

see view i am getting

Upvotes: 0

Divya
Divya

Reputation: 543

Here is my answer using the same Observablegridview, which got to work after some analysis and modifications while scrolling the grid.

For the grid of image to be displayed, use this ObservableGridView.java

Here is the xml layout

  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/mainFrame">

    <com.sampleapp.Observablescroll.ObservableGridView
        android:id="@+id/camera_gridView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:numColumns="4" />

    <RelativeLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RelativeLayout
            android:id="@+id/gallery_lay"
            android:layout_width="wrap_content"
            android:layout_height="365dp"
            android:background="@color/black"
            android:orientation="vertical">

            <com.fenchtose.nocropper.CropperImageView
                android:id="@+id/gallery_click_img"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentTop="true"
                android:scaleType="centerCrop"
                app:grid_color="@color/action_bar_color" /> 

        </RelativeLayout>

        <View
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="300dp" />

    </RelativeLayout>
</FrameLayout>

In your java class, implement ObservableScrollViewCallbacks

        mHeaderView = (RelativeLayout) rootview.findViewById(R.id.header);
        mToolbarView = rootview.findViewById(R.id.toolbar);
        camera_gridView = (ObservableGridView) rootview.findViewById(R.id.camera_gridView);


        LayoutInflater inflaters = LayoutInflater.from(getActivity());
        camera_gridView.addHeaderView(inflaters.inflate(R.layout.image_holder_view, camera_gridView, false)); 
// view that leaves 300dp space to display the selected image from the grid 
      camera_gridView.addHeaderView(inflaters.inflate(R.layout.sticky_tool_bar_view, camera_gridView, false)); 
// a sticky view with action bar's height, so that the grid doesn't scroll above this

        camera_gridView.setScrollViewCallbacks(this);


//overridden methods

   @Override
    public void onScrollChanged(int scrollY, boolean firstScroll, boolean dragging) {
        if (dragging) {
            int toolbarHeight = mToolbarView.getHeight();
            //    int toolbarHeight = 300;
            if (camera_gridView.getCurrentScrollY() == 0) {
                showToolbar();

        }
        if (firstScroll) {

            float currentHeaderTranslationY = ViewHelper.getTranslationY(mHeaderView);
            if (-toolbarHeight < currentHeaderTranslationY) {
                mBaseTranslationY = scrollY;
            }
        }
        float headerTranslationY = ScrollUtils.getFloat(-(scrollY - mBaseTranslationY), -toolbarHeight, 0);
        ViewPropertyAnimator.animate(mHeaderView).cancel();
        ViewHelper.setTranslationY(mHeaderView, headerTranslationY);
    }
}

@Override
public void onDownMotionEvent() {

}

@Override
public void onUpOrCancelMotionEvent(ScrollState scrollState) {
    mBaseTranslationY = 0;

    if (scrollState == ScrollState.DOWN) {
        int toolbarHeight = mToolbarView.getHeight();
        if (camera_gridView.getCurrentScrollY() == 0) {
            showToolbar();

        }
        int scrollY = camera_gridView.getCurrentScrollY();
        if (toolbarHeight <= scrollY) {
            hideToolbar();

        } else {
            showToolbar();
        }

    } else if (scrollState == ScrollState.UP) {
        int toolbarHeight = mToolbarView.getHeight();
        int scrollY = camera_gridView.getCurrentScrollY();
        if (toolbarHeight <= scrollY) {
            System.out.println("++++upif" + scrollY);
            hideToolbar();
        } else {
            System.out.println("++++upelse" + scrollY);
            showToolbar();
        }
        if (camera_gridView.getCurrentScrollY() == 0) {
            showToolbar();
        }
    } else {
        if (!toolbarIsShown() && !toolbarIsHidden()) {
            showToolbar();
        }
    }
}

//method to show the toolbar
    private void showToolbar() {
        float headerTranslationY = ViewHelper.getTranslationY(mHeaderView);
        if (headerTranslationY != 0) {
            ViewPropertyAnimator.animate(mHeaderView).cancel();
            ViewPropertyAnimator.animate(mHeaderView).translationY(0).setDuration(200).start();
        }
    }

//method to hide the toolbar
    private void hideToolbar() {
        float headerTranslationY = ViewHelper.getTranslationY(mHeaderView);
        int toolbarHeight = mToolbarView.getHeight();
        if (headerTranslationY != -toolbarHeight) {
            ViewPropertyAnimator.animate(mHeaderView).cancel();
            ViewPropertyAnimator.animate(mHeaderView).translationY(-toolbarHeight).setDuration(200).start();
        }
    }

   private boolean toolbarIsShown() {
        return ViewHelper.getTranslationY(mHeaderView) == 0;
    }
private boolean toolbarIsHidden() {
    return ViewHelper.getTranslationY(mHeaderView) == -mToolbarView.getHeight();
}

Upvotes: 1

Related Questions