diff --git a/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java b/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java index 152f24c7ba..98c5f1e17a 100644 --- a/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java +++ b/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java @@ -41,6 +41,7 @@ import com.owncloud.android.ui.activities.data.files.FilesRepository; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.adapter.ActivityListAdapter; +import com.owncloud.android.ui.adapter.StickyHeaderAdapter; import com.owncloud.android.ui.interfaces.ActivityListInterface; import com.owncloud.android.ui.preview.PreviewImageActivity; import com.owncloud.android.ui.preview.PreviewImageFragment; @@ -174,7 +175,7 @@ public class ActivitiesActivity extends FileActivity implements ActivityListInte LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); - recyclerView.addItemDecoration(new ActivityListItemDecoration()); + recyclerView.addItemDecoration(new ActivityListItemDecoration( adapter)); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override diff --git a/src/main/java/com/owncloud/android/ui/activities/ActivityListItemDecoration.java b/src/main/java/com/owncloud/android/ui/activities/ActivityListItemDecoration.java index ec7b406cd7..52339c7bc4 100644 --- a/src/main/java/com/owncloud/android/ui/activities/ActivityListItemDecoration.java +++ b/src/main/java/com/owncloud/android/ui/activities/ActivityListItemDecoration.java @@ -2,35 +2,54 @@ package com.owncloud.android.ui.activities; import android.graphics.Canvas; import android.graphics.Color; +import android.util.Log; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; -import com.owncloud.android.ui.adapter.ActivityListAdapter; +import com.owncloud.android.R; + +import com.owncloud.android.ui.adapter.StickyHeaderAdapter; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; public class ActivityListItemDecoration extends RecyclerView.ItemDecoration { private final String TAG = this.getClass().getSimpleName(); - private View currentHeader; + private final StickyHeaderAdapter adapter; + + + public ActivityListItemDecoration(StickyHeaderAdapter stickyHeaderAdapter) { + this.adapter = stickyHeaderAdapter; + } @Override public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDrawOver(c, parent, state); - View topChild = parent.getChildAt(0); - int topChildPosition = parent.getChildAdapterPosition(topChild); - if (topChildPosition == -1) { + if (topChild == null) { return; } - ActivityListAdapter adapter = (ActivityListAdapter) parent.getAdapter(); + int topChildPosition = parent.getChildAdapterPosition(topChild); - Object topElement = adapter.getActivityAtByPosition(topChildPosition); - - if (topElement instanceof ActivityListHeader) { - currentHeader = parent.getChildAt(0); - currentHeader.setBackgroundColor(Color.WHITE); + if (topChildPosition == RecyclerView.NO_POSITION) { + return; } + View currentHeader = getHeaderViewForItem(topChildPosition, parent); + fixLayoutSize(parent, currentHeader); + int contactPoint = currentHeader.getBottom(); + View childInContact = getChildInContact(parent, contactPoint); + + if (childInContact == null) { + return; + } + + if (adapter.isHeader(parent.getChildAdapterPosition(childInContact))) { + moveHeader(c, currentHeader, childInContact); + return; + } + drawHeader(c, currentHeader); } @@ -40,4 +59,50 @@ public class ActivityListItemDecoration extends RecyclerView.ItemDecoration { header.draw(c); c.restore(); } + + private void moveHeader(Canvas c, View currentHeader, View nextHeader) { + c.save(); + c.translate(0, nextHeader.getTop() - currentHeader.getHeight()); + currentHeader.draw(c); + c.restore(); + } + + private View getChildInContact(RecyclerView parent, int contactPoint) { + View childInContact = null; + for (int i = 0; i < parent.getChildCount(); i++) { + View currentChild = parent.getChildAt(i); + if (currentChild.getBottom() > contactPoint) { + if (currentChild.getTop() <= contactPoint) { + childInContact = currentChild; + break; + } + } + } + return childInContact; + } + + private View getHeaderViewForItem(int itemPosition, RecyclerView parent) { + int headerPosition = adapter.getHeaderPositionForItem(itemPosition); + int layoutId = adapter.getHeaderLayout(itemPosition); + View header = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); + header.setBackgroundColor(Color.WHITE); + adapter.bindHeaderData(header, headerPosition); + return header; + } + + private void fixLayoutSize(ViewGroup parent, View view) { + + // Specs for parent (RecyclerView) + int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY); + int heightSpec = View.MeasureSpec.makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED); + + // Specs for children (headers) + int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, parent.getPaddingLeft() + parent.getPaddingRight(), view.getLayoutParams().width); + int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, parent.getPaddingTop() + parent.getPaddingBottom(), view.getLayoutParams().height); + + view.measure(childWidthSpec, childHeightSpec); + view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); + } + + } diff --git a/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java index 702e3080f1..ef793421b8 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java @@ -80,12 +80,13 @@ import java.util.List; import java.util.Locale; import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; /** * Adapter for the activity view */ -public class ActivityListAdapter extends RecyclerView.Adapter { +public class ActivityListAdapter extends RecyclerView.Adapter implements StickyHeaderAdapter { static final int HEADER_TYPE = 100; static final int ACTIVITY_TYPE = 101; @@ -142,7 +143,7 @@ public class ActivityListAdapter extends RecyclerView.Adapter= 0); + return headerPosition; + } + + @Override + public int getHeaderLayout(int headerPosition) { + return R.layout.activity_list_item_header; + } + + @Override + public void bindHeaderData(View header, int headerPosition) { + TextView textView = header.findViewById(R.id.title_header); + String headline = (String) values.get(headerPosition); + textView.setText(headline); + } + + @Override + public boolean isHeader(int itemPosition) { + return this.getItemViewType(itemPosition) == HEADER_TYPE; + } + protected class ActivityViewHolder extends RecyclerView.ViewHolder { private final ImageView activityIcon; @@ -453,7 +480,7 @@ public class ActivityListAdapter extends RecyclerView.Adapter