From 0991bff02b38bafde16c55fdfa631a10f8bfeaf3 Mon Sep 17 00:00:00 2001 From: Floens Date: Sun, 25 Oct 2015 13:23:35 +0100 Subject: [PATCH] Fix incorrect restoring of the scroll position --- .../chan/ui/controller/ThreadController.java | 11 +- .../floens/chan/ui/layout/ThreadLayout.java | 7 -- .../chan/ui/layout/ThreadListLayout.java | 111 +++++++++++------- .../org/floens/chan/utils/AndroidUtils.java | 4 +- .../src/main/res/drawable-mdpi/partyhat.png | Bin 0 -> 2365 bytes 5 files changed, 75 insertions(+), 58 deletions(-) create mode 100644 Clover/app/src/main/res/drawable-mdpi/partyhat.png diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java index 20a332cf..0d64508e 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java @@ -44,7 +44,6 @@ import java.util.List; import de.greenrobot.event.EventBus; import static org.floens.chan.utils.AndroidUtils.dp; -import static org.floens.chan.utils.AndroidUtils.isTablet; public abstract class ThreadController extends Controller implements ThreadLayout.ThreadLayoutCallback, ImageViewerController.PreviewCallback, SwipeRefreshLayout.OnRefreshListener, ToolbarNavigationController.ToolbarSearchCallback, NfcAdapter.CreateNdefMessageCallback { private static final String TAG = "ThreadController"; @@ -62,7 +61,7 @@ public abstract class ThreadController extends Controller implements ThreadLayou EventBus.getDefault().register(this); - navigationItem.collapseToolbar = !isTablet(context); + navigationItem.collapseToolbar = true; threadLayout = (ThreadLayout) LayoutInflater.from(context).inflate(R.layout.layout_thread, null); threadLayout.setCallback(this); @@ -76,9 +75,8 @@ public abstract class ThreadController extends Controller implements ThreadLayou swipeRefreshLayout.addView(threadLayout); swipeRefreshLayout.setOnRefreshListener(this); - ToolbarNavigationController toolbarNavigationController = (ToolbarNavigationController) navigationController; - if (collapseToolbar()) { + if (navigationItem.collapseToolbar) { int toolbarHeight = getToolbar().getToolbarHeight(); swipeRefreshLayout.setProgressViewOffset(false, toolbarHeight - dp(40), toolbarHeight + dp(64 - 40)); } @@ -203,11 +201,6 @@ public abstract class ThreadController extends Controller implements ThreadLayou return ((ToolbarNavigationController) navigationController).getToolbar(); } - @Override - public boolean collapseToolbar() { - return navigationItem.collapseToolbar; - } - @Override public void onSearchVisibilityChanged(boolean visible) { threadLayout.getPresenter().onSearchVisibilityChanged(visible); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java index 12c5bdb2..0d6d10da 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java @@ -197,11 +197,6 @@ public class ThreadLayout extends CoordinatorLayout implements ThreadPresenter.T return callback.getToolbar(); } - @Override - public boolean collapseToolbar() { - return callback.collapseToolbar(); - } - @Override public void showPosts(ChanThread thread, PostsFilter filter) { threadListLayout.showPosts(thread, filter, visible != Visible.THREAD); @@ -519,7 +514,5 @@ public class ThreadLayout extends CoordinatorLayout implements ThreadPresenter.T void hideSwipeRefreshLayout(); Toolbar getToolbar(); - - boolean collapseToolbar(); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadListLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadListLayout.java index 1165f545..1a90a986 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadListLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadListLayout.java @@ -18,6 +18,9 @@ package org.floens.chan.ui.layout; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -44,6 +47,7 @@ import org.floens.chan.ui.view.ThumbnailView; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.AnimationUtils; +import java.util.Calendar; import java.util.List; import static org.floens.chan.utils.AndroidUtils.ROBOTO_MEDIUM; @@ -51,7 +55,7 @@ import static org.floens.chan.utils.AndroidUtils.dp; import static org.floens.chan.utils.AndroidUtils.getAttrColor; /** - * A layout that wraps around a {@link RecyclerView} to manage showing posts. + * A layout that wraps around a {@link RecyclerView} and a {@link ReplyLayout} to manage showing and replying to posts. */ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLayoutCallback { public static final int MAX_SMOOTH_SCROLL_DISTANCE = 20; @@ -102,9 +106,16 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa public void onScrolled(RecyclerView recyclerView, int dx, int dy) { // onScrolled can be called after cleanup() if (showingThread != null) { - int index = Math.max(0, getTopAdapterPosition()); - View topChild = recyclerView.getLayoutManager().getChildAt(0); - int top = topChild == null ? 0 : topChild.getTop(); + int index = 0; + int top = 0; + if (recyclerView.getChildCount() > 0) { + View topChild = recyclerView.getLayoutManager().getChildAt(0); + + index = ((RecyclerView.LayoutParams) topChild.getLayoutParams()).getViewLayoutPosition(); + + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) topChild.getLayoutParams(); + top = layoutManager.getDecoratedTop(topChild) - params.topMargin - recyclerView.getPaddingTop(); + } showingThread.loadable.listViewIndex = index; showingThread.loadable.listViewTop = top; @@ -120,8 +131,8 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa attachToolbarScroll(true); - reply.setPadding(0, topSpacing(), 0, 0); - searchStatus.setPadding(searchStatus.getPaddingLeft(), searchStatus.getPaddingTop() + topSpacing(), + reply.setPadding(0, toolbarHeight(), 0, 0); + searchStatus.setPadding(searchStatus.getPaddingLeft(), searchStatus.getPaddingTop() + toolbarHeight(), searchStatus.getPaddingRight(), searchStatus.getPaddingBottom()); } @@ -147,7 +158,7 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa case LIST: LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext()); recyclerViewTopPadding = 0; - recyclerView.setPadding(0, recyclerViewTopPadding + topSpacing(), 0, 0); + recyclerView.setPadding(0, recyclerViewTopPadding + toolbarHeight(), 0, 0); recyclerView.setLayoutManager(linearLayoutManager); layoutManager = linearLayoutManager; @@ -161,7 +172,7 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa GridLayoutManager gridLayoutManager = new GridLayoutManager(null, spanCount, GridLayoutManager.VERTICAL, false); // The cards have a 4dp padding, this way there is always 8dp between the edges recyclerViewTopPadding = dp(4); - recyclerView.setPadding(dp(4), recyclerViewTopPadding + topSpacing(), dp(4), dp(4)); + recyclerView.setPadding(dp(4), recyclerViewTopPadding + toolbarHeight(), dp(4), dp(4)); recyclerView.setLayoutManager(gridLayoutManager); layoutManager = gridLayoutManager; @@ -188,14 +199,19 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa recyclerView.setLayoutManager(layoutManager); recyclerView.getRecycledViewPool().clear(); + int index = thread.loadable.listViewIndex; + int top = thread.loadable.listViewTop; + switch (postViewMode) { case LIST: - ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(thread.loadable.listViewIndex, thread.loadable.listViewTop); + ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(index, top); break; case CARD: - ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(thread.loadable.listViewIndex, thread.loadable.listViewTop); + ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(index, top); break; } + + party(); } postAdapter.setThread(thread, filter); @@ -237,7 +253,7 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + height, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); } else { AndroidUtils.hideKeyboard(reply); - recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + topSpacing(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); + recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + toolbarHeight(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); } threadListLayoutCallback.replyLayoutOpen(open); @@ -254,7 +270,7 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa } public void openSearch(boolean show) { - if (searchOpen != show) { + if (showingThread != null && searchOpen != show) { searchOpen = show; int height = AnimationUtils.animateHeight(searchStatus, show); @@ -262,7 +278,7 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa searchStatus.setText(R.string.search_empty); recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + height, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); } else { - recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + topSpacing(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); + recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + toolbarHeight(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom()); } attachToolbarScroll(!(show || replyOpen)); @@ -294,13 +310,13 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa case LIST: if (getTopAdapterPosition() == 0) { View top = layoutManager.findViewByPosition(0); - return top.getTop() != topSpacing(); + return top.getTop() != toolbarHeight(); } break; case CARD: if (getTopAdapterPosition() == 0) { View top = layoutManager.findViewByPosition(0); - return top.getTop() != dp(8) + topSpacing(); // 4dp for the cards, 4dp for this layout + return top.getTop() != dp(8) + toolbarHeight(); // 4dp for the cards, 4dp for this layout } break; } @@ -312,27 +328,13 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa } public void cleanup() { - /*if (ChanBuild.DEVELOPER_MODE) { - Pin pin = ChanApplication.getWatchManager().findPinByLoadable(showingThread.loadable); - if (pin == null) { - for (Post post : showingThread.posts) { - if (post.comment instanceof SpannedString) { - SpannedString commentSpannable = (SpannedString) post.comment; - PostLinkable[] linkables = commentSpannable.getSpans(0, commentSpannable.length(), PostLinkable.class); - for (PostLinkable linkable : linkables) { - ChanApplication.getRefWatcher().watch(linkable, linkable.key + " " + linkable.value); - } - } - } - } - }*/ - postAdapter.cleanup(); reply.cleanup(); openReply(false); openSearch(false); showingThread = null; lastPostCount = 0; + noParty(); } public List getDisplayingPosts() { @@ -419,8 +421,8 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa } private void attachToolbarScroll(boolean attach) { - Toolbar toolbar = threadListLayoutCallback.getToolbar(); - if (toolbar != null && threadListLayoutCallback.collapseToolbar()) { + if (!AndroidUtils.isTablet(getContext())) { + Toolbar toolbar = threadListLayoutCallback.getToolbar(); if (attach) { toolbar.attachRecyclerViewScrollStateListener(recyclerView); } else { @@ -430,13 +432,9 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa } } - private int topSpacing() { + private int toolbarHeight() { Toolbar toolbar = threadListLayoutCallback.getToolbar(); - if (toolbar != null && threadListLayoutCallback.collapseToolbar()) { - return toolbar.getToolbarHeight(); - } else { - return 0; - } + return toolbar.getToolbarHeight(); } private int getTopAdapterPosition() { @@ -459,6 +457,41 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa return -1; } + private Bitmap hat; + + private final RecyclerView.ItemDecoration PARTY = new RecyclerView.ItemDecoration() { + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + if (hat == null) { + hat = BitmapFactory.decodeResource(getResources(), R.drawable.partyhat); + } + + for (int i = 0, j = parent.getChildCount(); i < j; i++) { + View child = parent.getChildAt(i); + if (child instanceof PostCellInterface) { + PostCellInterface postView = (PostCellInterface) child; + if (postView.getPost().hasImage) { + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + int top = child.getTop() + params.topMargin; + int left = child.getLeft() + params.leftMargin; + c.drawBitmap(hat, left - parent.getPaddingLeft() - dp(40), top - dp(130) - parent.getPaddingTop() + toolbarHeight(), null); + } + } + } + } + }; + + private void party() { + Calendar calendar = Calendar.getInstance(); + if (calendar.get(Calendar.MONTH) == Calendar.OCTOBER && calendar.get(Calendar.DAY_OF_MONTH) == 1) { + recyclerView.addItemDecoration(PARTY); + } + } + + private void noParty() { + recyclerView.removeItemDecoration(PARTY); + } + public interface ThreadListLayoutPresenterCallback { void showThread(Loadable loadable); @@ -471,7 +504,5 @@ public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLa void replyLayoutOpen(boolean open); Toolbar getToolbar(); - - boolean collapseToolbar(); } } diff --git a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java index aa845d6e..9979597e 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java @@ -230,8 +230,8 @@ public class AndroidUtils { } public static void hideKeyboard(View view) { - InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0); } public static String getReadableFileSize(long bytes, boolean si) { diff --git a/Clover/app/src/main/res/drawable-mdpi/partyhat.png b/Clover/app/src/main/res/drawable-mdpi/partyhat.png new file mode 100644 index 0000000000000000000000000000000000000000..60ed6c2df9f345163a1761ecdf08814982250b78 GIT binary patch literal 2365 zcmYM0eKgbk8^^cU%wkGSqj~t*ukI4r*P15sG^~^?SuyUmwLFbjMpR^p87-?6E5)LO z!mT1|W}Y@h(Vd4#HPqHk59BCB-BaiMet%pKpVzt0=bZQTxjyGyndDt0eYgo61On-A z-{#?`iQ+|rK{ft#SD1|^XotD^xPd^`!lm;Jh~})z-WJFKfee2cSYTPNqk*V6&w#i+ zF`;n@jMxwmn-LKmw=p^-&SKL>>_+=}0rL$A1bevM!_7Z&|Hmt*&kcDQdPK+qF^+F# z^@oqN|55K2^VNR^rPyPaeK*JiMPEy6U7Fc&CZ+-9H*&sF0LW3y|GDQ)DL=kV<@}s; zPx@H(#>ItmTrjXRjiUPdpp5`zdd-37lJYYR{bz^MW04!db!xAj>@{p^9rFn2*^~5r zjbB@6TD+r1O#5zQ+K!(J{(yq_o~klF6WAp8b?zxl4K=?C{!+D&Xwwzi34Nc#-sp{F z%;UNac6zOA#;c4415NUoW~WntV}LO|`GD$~{DT-L4U0o`=|P%f6IDqj!|9VXg+G7n z>?{@-dz^T1IMK>kCtRLWU2P?`6K+xw{1Zc>fyEFWjZ>lgSzA$e<3VRuNFzuIg+N7!%W{zYAx7n)6lHA=e}5mshq{-&MYx!PZWX$JrE=0jHzRvvIQOKORJ>9oUkQNy| z8%Ux&z^er;f3xBgxT06nX(ZC(ho@&wqP_M%zHZMw+rIG+vbm^X44Wy+vTX$c4{X3Z zB;B(hZ94<7y zG?X(NwYH^X!qOh`sU1W~JDRUrkvZ(kvl(&3$g;W$Q)ym$DR$xTs@8xR1x66**lc^9 zM~h8dBQNUv8qj})OWOt^1N6A?WYcfTK{LRPG!xQF2A~22E3UX*B z(4152H=wt*4_~ZEmb^9`4Pu*nAu z=kxU|oIC_RWnblux9DDunYPko^G`QA6?O?Hb@D`G|h1%i~84 zTV&shp*M?&0Bk5@oHP?#g%V>Vf5e6_%Qq}0U|i#c2Byk|;gfALpf(q&cn1Em(C{Ai z*+*YDBl}v-?FJH*za0N34Er=k$g13?uiMs5Enlds-G_+iy965#o~=`{dd`ydDncS% zDr1mZW3m5{Va@x4_0fNG0+#uA^qmN%ZQ$J<^h!(olys1@2Fo=(#TpnCjyE`C21ngB zUAt3nND!;V7Nxlr3w5tY|6A0M1)HVLzED{yx!!u^i}%_(WQL_J1@ji+1lNq1DyG(c z9X-~O$M%AQ<@XPjjjN0EH(2OsyVXQ}RK(v9gkE1M&cd3%lH{XM25P_p#(Fx~)fgjC z!)cZdRK8|HSFPo($r-|HpNq=p21nQNM;?V^$ zx2#0xzD$4V72%Y5v;!Uu<;=+|LHK+*o*$+{AM2D;*b z@Rv5MyWXw-zR9}%<=Cg>S39KeDMXK}yI!e=)s&3pa>DMs(Dice}wxCojYF#8tv+Q0xpIXoSp)#%L~8~8H$YAnYyL7Ag1^r8VMlp(Q(gR~tr^ah^_DDpP%{w& ztvPaG%(ywpgA?CFCT1^cEIfX}N`f_iG6ca7oh6R#HdUx!m1pTcQ2+@Z`sjD1nqQGv zU{n60J4u_9&@(Y`gNEsIuBqLNT%CVE+8Kg$-!X5iTGm)=?}XgfA)!n?Y86w~6~C*a zst#R>A$sE6k%6K-d?-Als0e=a&H1Cp{=aGb&Mwc-O{e(TpNUNi6<^k@I-u>IyF4o0 H>8bw$RC_^; literal 0 HcmV?d00001