Reputation: 543
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:
I'm right now using, Observablegrid view, which is of not that much use!
Please suggest any ideas. Thanks!
Upvotes: 7
Views: 3010
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
Upvotes: 0
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