Skip to content

Commit

Permalink
Optimize post lines limit
Browse files Browse the repository at this point in the history
  • Loading branch information
Mishiranu committed Sep 16, 2020
1 parent 03991f1 commit 9c2e682
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 111 deletions.
155 changes: 74 additions & 81 deletions src/com/mishiranu/dashchan/ui/navigator/manager/ViewUnit.java
Expand Up @@ -69,7 +69,6 @@ public class ViewUnit {

private final int commentMaxLines;
private final int commentAdditionalHeight;
private final int commentAdditionalLines;

private static final float ALPHA_HIDDEN_POST = 0.2f;
private static final float ALPHA_DELETED_POST = 0.5f;
Expand All @@ -96,7 +95,6 @@ public class ViewUnit {
view.measure(widthMeasureSpec, heightMeasureSpec);
commentMaxLines = Preferences.getPostMaxLines();
commentAdditionalHeight = bottomBar.getMeasuredHeight();
commentAdditionalLines = (int) Math.ceil(commentAdditionalHeight / comment.getTextSize());
thumbnailWidth = head.getMeasuredHeight();
int additionalAttachmentInfoWidthDp = 64; // approximately equal to thumbnail width + right padding
int minAttachmentInfoWidthDp = additionalAttachmentInfoWidthDp + 68;
Expand Down Expand Up @@ -362,16 +360,13 @@ public void bindPostView(RecyclerView.ViewHolder viewHolder, PostItem postItem,
holder.bottomBarExpand.setVisibility(View.GONE);
holder.bottomBarOpenThread.setVisibility(demandSet.showOpenThreadButton ? View.VISIBLE : View.GONE);
}
if (holder.configurationSet.mayCollapse) {
// invalidateBottomBar will be called from these following methods
if (commentMaxLines == 0 || postItem.isExpanded()) {
removeMaxHeight(holder);
} else {
setMaxHeight(holder);
}
if (holder.configurationSet.mayCollapse && commentMaxLines > 0 && !postItem.isExpanded()) {
holder.comment.setLinesLimit(commentMaxLines, commentAdditionalHeight);
} else {
invalidateBottomBar(holder);
holder.comment.setLinesLimit(0, 0);
}
holder.bottomBarExpand.setVisibility(View.GONE);
holder.invalidateBottomBar();

boolean viewsEnabled = demandSet.selection == UiManager.Selection.DISABLED;
holder.thumbnail.setEnabled(viewsEnabled);
Expand Down Expand Up @@ -577,76 +572,6 @@ private void handlePostViewIcons(PostViewHolder holder) {
}
}

private void invalidateBottomBar(PostViewHolder holder) {
boolean repliesVisible = holder.bottomBarReplies.getVisibility() == View.VISIBLE;
boolean expandVisible = holder.bottomBarExpand.getVisibility() == View.VISIBLE;
boolean openThreadVisible = holder.bottomBarOpenThread.getVisibility() == View.VISIBLE;
boolean needBar = repliesVisible || expandVisible || openThreadVisible;
holder.bottomBarReplies.getLayoutParams().width = repliesVisible && !expandVisible && !openThreadVisible ?
ViewGroup.LayoutParams.MATCH_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT;
holder.bottomBarExpand.getLayoutParams().width = expandVisible && !openThreadVisible ?
ViewGroup.LayoutParams.MATCH_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT;
holder.bottomBar.setVisibility(needBar ? View.VISIBLE : View.GONE);
boolean hasText = holder.comment.getVisibility() == View.VISIBLE;
float density = ResourceUtils.obtainDensity(holder.comment);
holder.textBarPadding.getLayoutParams().height = (int) ((needBar ? 0f : hasText ? 10f : 6f) * density);
}

private void setMaxHeight(PostViewHolder holder) {
clearMaxHeightAnimation(holder);
holder.comment.setMaxHeight(Integer.MAX_VALUE);
int width = (int) (ResourceUtils.obtainDensity(holder.itemView) *
holder.itemView.getResources().getConfiguration().screenWidthDp);
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.AT_MOST);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
holder.comment.measure(widthMeasureSpec, heightMeasureSpec);
if (holder.comment.getLineCount() >= commentMaxLines + commentAdditionalLines) {
holder.comment.setMaxLines(commentMaxLines);
holder.bottomBarExpand.setVisibility(View.VISIBLE);
holder.bottomBarExpand.setOnClickListener(v -> {
holder.postItem.setExpanded(true);
removeMaxHeight(holder);
int fromHeight = holder.comment.getHeight();
AnimationUtils.measureDynamicHeight(holder.comment);
int toHeight = holder.comment.getMeasuredHeight();
// When button bar becomes hidden, height of view becomes smaller, so it can cause
// little jumping of list; This is solution - start animation from item_height + bar_height
if (holder.bottomBar.getVisibility() == View.GONE) {
fromHeight += commentAdditionalHeight;
}
if (toHeight > fromHeight) {
float density = ResourceUtils.obtainDensity(holder.comment);
float value = (toHeight - fromHeight) / density / 400;
if (value > 1f) {
value = 1f;
} else if (value < 0.2f) {
value = 0.2f;
}
Animator heightAnimator = AnimationUtils.ofHeight(holder.comment, fromHeight,
ViewGroup.LayoutParams.WRAP_CONTENT, false);
heightAnimator.setDuration((int) (200 * value));
heightAnimator.start();
}
});
} else {
holder.comment.setMaxHeight(Integer.MAX_VALUE);
holder.bottomBarExpand.setVisibility(View.GONE);
}
invalidateBottomBar(holder);
}

private void removeMaxHeight(PostViewHolder holder) {
clearMaxHeightAnimation(holder);
holder.comment.setMaxHeight(Integer.MAX_VALUE);
holder.bottomBarExpand.setVisibility(View.GONE);
invalidateBottomBar(holder);
}

private void clearMaxHeightAnimation(PostViewHolder holder) {
holder.comment.clearAnimation();
holder.comment.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
}

private CharSequence makeHighlightedText(Collection<String> highlightText, CharSequence text) {
if (!highlightText.isEmpty() && text != null) {
Locale locale = Locale.getDefault();
Expand Down Expand Up @@ -1040,7 +965,8 @@ public void cancel() {
}

private static class PostViewHolder extends RecyclerView.ViewHolder implements UiManager.Holder,
CommentTextView.RecyclerKeeper.Holder, PostLinearLayout.OnTemporaryDetachListener {
CommentTextView.RecyclerKeeper.Holder, PostLinearLayout.OnTemporaryDetachListener,
CommentTextView.LimitListener, View.OnClickListener {
public final PostLinearLayout layout;
public final LinebreakLayout head;
public final TextView number;
Expand Down Expand Up @@ -1069,6 +995,7 @@ private static class PostViewHolder extends RecyclerView.ViewHolder implements U
public final UiManager.ThumbnailLongClickListener thumbnailLongClickListener;

public PostItem postItem;
public Animator expandAnimator;
public NewPostAnimation newPostAnimation;
public long lastCommentClick;

Expand Down Expand Up @@ -1115,10 +1042,12 @@ public PostViewHolder(ViewGroup parent, UiManager.ConfigurationSet configuration
thumbnailLongClickListener = uiManager.interaction().createThumbnailLongClickListener();

head.setOnTouchListener(uiManager.view().headContentTouchListener);
comment.setLimitListener(this);
comment.setCommentListener(uiManager.view().commentListener);
thumbnail.setOnClickListener(thumbnailClickListener);
thumbnail.setOnLongClickListener(thumbnailLongClickListener);
bottomBarReplies.setOnClickListener(uiManager.view().repliesBlockClickListener);
bottomBarExpand.setOnClickListener(this);
bottomBarOpenThread.setOnClickListener(uiManager.view().threadLinkBlockClickListener);

index.setTypeface(GraphicsUtils.TYPEFACE_MEDIUM);
Expand All @@ -1143,12 +1072,76 @@ public PostViewHolder(ViewGroup parent, UiManager.ConfigurationSet configuration
}

public void notifyUnbind() {
if (expandAnimator != null) {
expandAnimator.cancel();
expandAnimator = null;
comment.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
if (newPostAnimation != null) {
newPostAnimation.cancel();
newPostAnimation = null;
}
}

public void invalidateBottomBar() {
boolean repliesVisible = bottomBarReplies.getVisibility() == View.VISIBLE;
boolean expandVisible = bottomBarExpand.getVisibility() == View.VISIBLE;
boolean openThreadVisible = bottomBarOpenThread.getVisibility() == View.VISIBLE;
boolean needBar = repliesVisible || expandVisible || openThreadVisible;
bottomBarReplies.getLayoutParams().width = repliesVisible && !expandVisible && !openThreadVisible ?
ViewGroup.LayoutParams.MATCH_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT;
bottomBarExpand.getLayoutParams().width = expandVisible && !openThreadVisible ?
ViewGroup.LayoutParams.MATCH_PARENT : ViewGroup.LayoutParams.WRAP_CONTENT;
bottomBar.setVisibility(needBar ? View.VISIBLE : View.GONE);
boolean hasText = comment.getVisibility() == View.VISIBLE;
float density = ResourceUtils.obtainDensity(textBarPadding);
textBarPadding.getLayoutParams().height = (int) ((needBar ? 0f : hasText ? 10f : 6f) * density);
}

@Override
public void onApplyLimit(boolean limited) {
if (limited != (bottomBarExpand.getVisibility() == View.VISIBLE)) {
bottomBarExpand.setVisibility(limited ? View.VISIBLE : View.GONE);
invalidateBottomBar();
}
}

@Override
public void onClick(View v) {
if (v == bottomBarExpand && postItem != null && !postItem.isExpanded()) {
postItem.setExpanded(true);
comment.setLinesLimit(0, 0);
bottomBarExpand.setVisibility(View.GONE);
int bottomBarHeight = bottomBar.getHeight();
invalidateBottomBar();
if (expandAnimator != null) {
expandAnimator.cancel();
}
int fromHeight = comment.getHeight();
AnimationUtils.measureDynamicHeight(comment);
int toHeight = comment.getMeasuredHeight();
if (bottomBarHeight > 0 && bottomBar.getVisibility() == View.GONE) {
// When button bar becomes hidden, height of the view becomes smaller, so it can cause
// a short list jump; Solution - start the animation from fromHeight + bottomBarHeight
fromHeight += bottomBarHeight;
}
if (toHeight > fromHeight) {
float density = ResourceUtils.obtainDensity(comment);
float value = (toHeight - fromHeight) / density / 400;
if (value > 1f) {
value = 1f;
} else if (value < 0.2f) {
value = 0.2f;
}
Animator animator = AnimationUtils.ofHeight(comment, fromHeight,
ViewGroup.LayoutParams.WRAP_CONTENT, false);
this.expandAnimator = animator;
animator.setDuration((int) (200 * value));
animator.start();
}
}
}

@Override
public void onTemporaryDetach(PostLinearLayout view, boolean start) {
if (start) {
Expand Down
80 changes: 50 additions & 30 deletions src/com/mishiranu/dashchan/widget/CommentTextView.java
Expand Up @@ -53,14 +53,15 @@ public class CommentTextView extends TextView {
private float spanStartX, spanStartY;
private float lastX, lastY;
private long lastXYSet;
private int currentMax = Integer.MAX_VALUE, reservedMax;
private boolean maxModeLines;
private int linesLimit;
private int linesLimitAdditionalHeight;
private View selectionPaddingView;
private boolean useAdditionalPadding;

private ActionMode currentActionMode;
private Menu currentActionModeMenu;

private LimitListener limitListener;
private CommentListener commentListener;
private LinkListener linkListener;
private boolean spoilersEnabled;
Expand Down Expand Up @@ -132,14 +133,22 @@ public interface ClickableSpan {
public void setClicked(boolean clicked);
}

public interface LimitListener {
void onApplyLimit(boolean limited);
}

public interface CommentListener {
public void onRequestSiblingsInvalidate(CommentTextView view);
public String onPrepareToCopy(CommentTextView view, Spannable text, int start, int end);
void onRequestSiblingsInvalidate(CommentTextView view);
String onPrepareToCopy(CommentTextView view, Spannable text, int start, int end);
}

public interface LinkListener {
public void onLinkClick(CommentTextView view, String chanName, Uri uri, boolean confirmed);
public void onLinkLongClick(CommentTextView view, String chanName, Uri uri);
void onLinkClick(CommentTextView view, String chanName, Uri uri, boolean confirmed);
void onLinkLongClick(CommentTextView view, String chanName, Uri uri);
}

public void setLimitListener(LimitListener listener) {
limitListener = listener;
}

public void setCommentListener(CommentListener listener) {
Expand Down Expand Up @@ -188,9 +197,33 @@ public void setSubjectAndComment(CharSequence subject, CharSequence comment) {
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

boolean limited = false;
if (linesLimit > 0) {
Layout layout = getLayout();
int count = layout.getLineCount();
if (count > linesLimit) {
int removeHeight = layout.getLineTop(count) - layout.getLineTop(linesLimit);
if (removeHeight > linesLimitAdditionalHeight) {
if (!selectionMode) {
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() - removeHeight);
}
limited = true;
}
}
}
if (limitListener != null) {
limitListener.onApplyLimit(limited);
}
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);

// Cause mEditor.prepareCursorControllers() call to enabled selection controllers
// mSelectionControllerEnabled can be set to false before view laid out
setCursorVisible(false);
Expand All @@ -205,8 +238,8 @@ public void setSpoilersEnabled(boolean enabled) {
private void setSelectionMode(boolean selectionMode) {
if (this.selectionMode != selectionMode) {
this.selectionMode = selectionMode;
updateSelectablePaddings();
updateUseAdditionalPadding(false);
requestLayout();
if (!selectionMode && isFocused()) {
View rootView = ListViewUtils.getRootViewInList(this);
if (rootView != null) {
Expand All @@ -217,6 +250,7 @@ private void setSelectionMode(boolean selectionMode) {
}
}
}
requestLayout();
}
}

Expand Down Expand Up @@ -466,20 +500,20 @@ protected void onSelectionChanged(int selStart, int selEnd) {
}
}

public void setLinesLimit(int limit, int additionalHeight) {
this.linesLimit = limit;
this.linesLimitAdditionalHeight = additionalHeight;
requestLayout();
}

@Override
public void setMaxLines(int maxlines) {
reservedMax = 0;
currentMax = maxlines;
maxModeLines = true;
super.setMaxLines(maxlines);
public void setMaxLines(int maxLines) {
throw new UnsupportedOperationException();
}

@Override
public void setMaxHeight(int maxHeight) {
reservedMax = 0;
currentMax = maxHeight;
maxModeLines = false;
super.setMaxHeight(maxHeight);
throw new UnsupportedOperationException();
}

public void bindSelectionPaddingView(View selectionPaddingView) {
Expand All @@ -505,20 +539,6 @@ private void updateUseAdditionalPadding(boolean force) {
}
}

private void updateSelectablePaddings() {
if (selectionMode) {
reservedMax = currentMax;
super.setMaxHeight(Integer.MAX_VALUE);
} else if (reservedMax > 0) {
// Also will reset reservedMax
if (maxModeLines) {
setMaxLines(reservedMax);
} else {
setMaxHeight(reservedMax);
}
}
}

@Override
public void setTextIsSelectable(boolean selectable) {
// Unsupported operation
Expand Down

0 comments on commit 9c2e682

Please sign in to comment.