Use a TextView for the PostCell comment again

Maintaining FastTextView because too much of a mess to maintain
because the post comment uses spannables extensively and the caching
became too difficult.

It is still used for the "n replies" and the date, these have simple requirements.
multisite
Floens 10 years ago
parent 430c0963bd
commit 1a19303418
  1. 4
      Clover/app/src/main/java/org/floens/chan/controller/Controller.java
  2. 5
      Clover/app/src/main/java/org/floens/chan/controller/ui/NavigationControllerContainerLayout.java
  3. 94
      Clover/app/src/main/java/org/floens/chan/ui/cell/PostCell.java
  4. 5
      Clover/app/src/main/java/org/floens/chan/ui/text/FastTextView.java
  5. 2
      Clover/app/src/main/java/org/floens/chan/ui/text/FastTextViewMovementMethod.java
  6. 4
      Clover/app/src/main/res/layout/cell_post.xml

@ -118,7 +118,9 @@ public abstract class Controller {
} }
if (AndroidUtils.removeFromParentView(view)) { if (AndroidUtils.removeFromParentView(view)) {
Logger.test(getClass().getSimpleName() + " view removed onDestroy"); if (LOG_STATES) {
Logger.test(getClass().getSimpleName() + " view removed onDestroy");
}
} }
} }

@ -32,6 +32,7 @@ import android.widget.Scroller;
import org.floens.chan.controller.Controller; import org.floens.chan.controller.Controller;
import org.floens.chan.controller.NavigationController; import org.floens.chan.controller.NavigationController;
import org.floens.chan.utils.Time;
public class NavigationControllerContainerLayout extends FrameLayout { public class NavigationControllerContainerLayout extends FrameLayout {
private NavigationController navigationController; private NavigationController navigationController;
@ -183,12 +184,12 @@ public class NavigationControllerContainerLayout extends FrameLayout {
swipingController = navigationController.getTop(); swipingController = navigationController.getTop();
drawShadow = true; drawShadow = true;
// long start = Time.startTiming(); long start = Time.startTiming();
Controller below = getBelowTop(); Controller below = getBelowTop();
navigationController.beginSwipeTransition(swipingController, below); navigationController.beginSwipeTransition(swipingController, below);
// Time.endTiming("attach", start); Time.endTiming("attach", start);
} }
float translationX = Math.max(0, event.getX() - swipeStartEvent.getX()); float translationX = Math.max(0, event.getX() - swipeStartEvent.getX());

@ -36,18 +36,19 @@ import android.text.Spanned;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.AbsoluteSizeSpan; import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan; import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan; import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan; import android.text.style.UnderlineSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.volley.VolleyError; import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader; import com.android.volley.toolbox.ImageLoader;
@ -83,7 +84,7 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
private ThumbnailView thumbnailView; private ThumbnailView thumbnailView;
private FastTextView title; private FastTextView title;
private PostIcons icons; private PostIcons icons;
private FastTextView comment; private TextView comment;
private FastTextView replies; private FastTextView replies;
private ImageView options; private ImageView options;
private View divider; private View divider;
@ -94,6 +95,7 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
private int countrySizePx; private int countrySizePx;
private int paddingPx; private int paddingPx;
private boolean threadMode; private boolean threadMode;
private boolean ignoreNextOnClick;
private boolean bound = false; private boolean bound = false;
private Theme theme; private Theme theme;
@ -107,9 +109,15 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
private OnClickListener selfClicked = new OnClickListener() { private OnClickListener selfClicked = new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
callback.onPostClicked(post); if (ignoreNextOnClick) {
ignoreNextOnClick = false;
} else {
callback.onPostClicked(post);
}
} }
}; };
private PostViewMovementMethod commentMovementMethod = new PostViewMovementMethod();
private PostViewFastMovementMethod titleMovementMethod = new PostViewFastMovementMethod();
public PostCell(Context context) { public PostCell(Context context) {
super(context); super(context);
@ -130,7 +138,7 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
thumbnailView = (ThumbnailView) findViewById(R.id.thumbnail_view); thumbnailView = (ThumbnailView) findViewById(R.id.thumbnail_view);
title = (FastTextView) findViewById(R.id.title); title = (FastTextView) findViewById(R.id.title);
icons = (PostIcons) findViewById(R.id.icons); icons = (PostIcons) findViewById(R.id.icons);
comment = (FastTextView) findViewById(R.id.comment); comment = (TextView) findViewById(R.id.comment);
replies = (FastTextView) findViewById(R.id.replies); replies = (FastTextView) findViewById(R.id.replies);
options = (ImageView) findViewById(R.id.options); options = (ImageView) findViewById(R.id.options);
divider = findViewById(R.id.divider); divider = findViewById(R.id.divider);
@ -397,18 +405,17 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
commentText = post.comment; commentText = post.comment;
} }
comment.setText(new SpannableString(commentText)); comment.setText(commentText);
comment.setVisibility(isEmpty(commentText) && !post.hasImage ? GONE : VISIBLE); comment.setVisibility(isEmpty(commentText) && !post.hasImage ? GONE : VISIBLE);
if (commentClickable != threadMode) { if (commentClickable != threadMode) {
commentClickable = threadMode; commentClickable = threadMode;
if (commentClickable) { if (commentClickable) {
PostViewMovementMethod movementMethod = new PostViewMovementMethod(); comment.setMovementMethod(commentMovementMethod);
comment.setMovementMethod(movementMethod);
comment.setOnClickListener(selfClicked); comment.setOnClickListener(selfClicked);
if (noClickable) { if (noClickable) {
title.setMovementMethod(movementMethod); title.setMovementMethod(titleMovementMethod);
} }
} else { } else {
comment.setOnClickListener(null); comment.setOnClickListener(null);
@ -494,17 +501,17 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
* A MovementMethod that searches for PostLinkables.<br> * A MovementMethod that searches for PostLinkables.<br>
* See {@link PostLinkable} for more information. * See {@link PostLinkable} for more information.
*/ */
private class PostViewMovementMethod implements FastTextViewMovementMethod { private class PostViewMovementMethod extends LinkMovementMethod {
@Override @Override
public boolean onTouchEvent(@NonNull FastTextView widget, @NonNull Spanned buffer, @NonNull Spanned cachedBuffer, @NonNull MotionEvent event) { public boolean onTouchEvent(@NonNull TextView widget, @NonNull Spannable buffer, @NonNull MotionEvent event) {
int action = event.getActionMasked(); int action = event.getActionMasked();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_DOWN) { if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX(); int x = (int) event.getX();
int y = (int) event.getY(); int y = (int) event.getY();
x -= widget.getPaddingLeft(); x -= widget.getTotalPaddingLeft();
y -= widget.getPaddingTop(); y -= widget.getTotalPaddingTop();
x += widget.getScrollX(); x += widget.getScrollX();
y += widget.getScrollY(); y += widget.getScrollY();
@ -517,45 +524,58 @@ public class PostCell extends LinearLayout implements PostCellInterface, PostLin
if (link.length != 0) { if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) { if (action == MotionEvent.ACTION_UP) {
ignoreNextOnClick = true;
link[0].onClick(widget); link[0].onClick(widget);
removeBackgroundSpan(widget, cachedBuffer); buffer.removeSpan(BACKGROUND_SPAN);
} else if (action == MotionEvent.ACTION_DOWN && link[0] instanceof PostLinkable) { } else if (action == MotionEvent.ACTION_DOWN && link[0] instanceof PostLinkable) {
int spanStart = buffer.getSpanStart(link[0]); buffer.setSpan(BACKGROUND_SPAN, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]), 0);
int spanEnd = buffer.getSpanEnd(link[0]);
// Set the buffer on the visible buffer, not on the functional buffer
// This is because the visible buffer may be a cached one or may be in use multiple times
if (spanStart <= spanEnd && spanStart >= 0 && spanEnd >= 0 && spanStart <= cachedBuffer.length() && spanEnd <= cachedBuffer.length()) {
showBackgroundSpan(widget, cachedBuffer, spanStart, spanEnd);
} else {
Log.e(TAG, "Could not add the background span because it was out of range!");
}
} else if (action == MotionEvent.ACTION_CANCEL) { } else if (action == MotionEvent.ACTION_CANCEL) {
removeBackgroundSpan(widget, cachedBuffer); buffer.removeSpan(BACKGROUND_SPAN);
} }
return true; return true;
} else { } else {
removeBackgroundSpan(widget, cachedBuffer); buffer.removeSpan(BACKGROUND_SPAN);
return false;
} }
} }
return false; return true;
} }
}
private void showBackgroundSpan(FastTextView widget, Spanned buffer, int start, int end) { /**
if (buffer instanceof Spannable) { * A MovementMethod that searches for PostLinkables.<br>
((Spannable) buffer).setSpan(BACKGROUND_SPAN, start, end, 0); * This version is for the {@link FastTextView}.<br>
widget.invalidate(); * See {@link PostLinkable} for more information.
} */
} private class PostViewFastMovementMethod implements FastTextViewMovementMethod {
@Override
public boolean onTouchEvent(@NonNull FastTextView widget, @NonNull Spanned buffer, @NonNull MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
private void removeBackgroundSpan(FastTextView widget, Spanned buffer) { x -= widget.getPaddingLeft();
if (buffer instanceof Spannable) { y -= widget.getPaddingTop();
((Spannable) buffer).removeSpan(BACKGROUND_SPAN);
widget.invalidate(); x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
link[0].onClick(widget);
return true;
}
} }
return false;
} }
} }

@ -32,14 +32,13 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.ui.cell.PostCell;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;
import static org.floens.chan.utils.AndroidUtils.sp; import static org.floens.chan.utils.AndroidUtils.sp;
/** /**
* A simple implementation of a TextView that caches the used StaticLayouts for performance.<br> * A simple implementation of a TextView that caches the used StaticLayouts for performance.<br>
* This view was made for {@link PostCell} and may have untested behaviour with other layouts. * This view was made for {@link org.floens.chan.ui.cell.PostCell} and {@link org.floens.chan.ui.cell.CardPostCell }and may have untested behaviour with other layouts.
*/ */
public class FastTextView extends View { public class FastTextView extends View {
private static final String TAG = "FastTextView"; private static final String TAG = "FastTextView";
@ -130,7 +129,7 @@ public class FastTextView extends View {
boolean handled = false; boolean handled = false;
if (movementMethod != null && text instanceof Spanned && layout != null && isEnabled()) { if (movementMethod != null && text instanceof Spanned && layout != null && isEnabled()) {
handled |= movementMethod.onTouchEvent(this, (Spanned) text, (Spanned) layout.getText(), event); handled |= movementMethod.onTouchEvent(this, (Spanned) text, event);
} }
return handled || super.onTouchEvent(event); return handled || super.onTouchEvent(event);

@ -21,5 +21,5 @@ import android.text.Spanned;
import android.view.MotionEvent; import android.view.MotionEvent;
public interface FastTextViewMovementMethod { public interface FastTextViewMovementMethod {
boolean onTouchEvent(FastTextView widget, Spanned buffer, Spanned cachedBuffer, MotionEvent event); boolean onTouchEvent(FastTextView widget, Spanned buffer, MotionEvent event);
} }

@ -61,7 +61,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:layout_below="@id/title" android:layout_below="@id/title"
android:layout_toRightOf="@id/thumbnail_view" /> android:layout_toRightOf="@id/thumbnail_view" />
<org.floens.chan.ui.text.FastTextView <TextView
android:id="@+id/comment" android:id="@+id/comment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -69,7 +69,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:layout_alignWithParentIfMissing="true" android:layout_alignWithParentIfMissing="true"
android:layout_below="@id/icons" android:layout_below="@id/icons"
android:layout_toRightOf="@id/thumbnail_view" android:layout_toRightOf="@id/thumbnail_view"
app:textColor="?attr/text_color_primary" /> android:textColor="?attr/text_color_primary" />
<org.floens.chan.ui.text.FastTextView <org.floens.chan.ui.text.FastTextView
android:id="@+id/replies" android:id="@+id/replies"

Loading…
Cancel
Save