From b30614abe4f952b2ab202a75ce3fe6dcf75cee3e Mon Sep 17 00:00:00 2001
From: Howard Wu <40033067+Howard20181@users.noreply.github.com>
Date: Fri, 15 Oct 2021 23:58:54 +0800
Subject: [PATCH] [app] Add Expandable TextView (#1279)
* [app] Add Expandable TextView
---
.../manager/ui/fragment/ModulesFragment.java | 3 +-
.../manager/ui/widget/ExpandableTextView.java | 129 ++++++++++++++++++
app/src/main/res/layout/item_module.xml | 6 +-
app/src/main/res/values/strings.xml | 2 +
4 files changed, 137 insertions(+), 3 deletions(-)
create mode 100644 app/src/main/java/org/lsposed/manager/ui/widget/ExpandableTextView.java
diff --git a/app/src/main/java/org/lsposed/manager/ui/fragment/ModulesFragment.java b/app/src/main/java/org/lsposed/manager/ui/fragment/ModulesFragment.java
index 3f6644e8..8d57e41b 100644
--- a/app/src/main/java/org/lsposed/manager/ui/fragment/ModulesFragment.java
+++ b/app/src/main/java/org/lsposed/manager/ui/fragment/ModulesFragment.java
@@ -488,7 +488,8 @@ public class ModulesFragment extends BaseFragment implements ModuleUtil.ModuleLi
sb.setSpan(foregroundColorSpan, sb.length() - recommended.length(), sb.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
}
- holder.hint.setText(sb);
+ if (sb.length() == 0) holder.hint.setVisibility(View.GONE);
+ else holder.hint.setText(sb);
if (!isPick) {
holder.root.setAlpha(moduleUtil.isModuleEnabled(item.packageName) ? 1.0f : .5f);
diff --git a/app/src/main/java/org/lsposed/manager/ui/widget/ExpandableTextView.java b/app/src/main/java/org/lsposed/manager/ui/widget/ExpandableTextView.java
new file mode 100644
index 00000000..4f42162f
--- /dev/null
+++ b/app/src/main/java/org/lsposed/manager/ui/widget/ExpandableTextView.java
@@ -0,0 +1,129 @@
+/*
+ *
+ */
+
+package org.lsposed.manager.ui.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.text.Layout;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.transition.TransitionManager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import org.lsposed.manager.R;
+
+public class ExpandableTextView extends TextView {
+ private CharSequence text = null;
+ private int nextLines = 0;
+ private final int maxLines;
+ private final SpannableString collapse;
+ private final SpannableString expand;
+ private final SpannableStringBuilder sb = new SpannableStringBuilder();
+
+ public ExpandableTextView(Context context) {
+ this(context, null);
+ }
+
+ public ExpandableTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ExpandableTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ maxLines = getMaxLines();
+ collapse = new SpannableString(context.getString(R.string.collapse));
+ ClickableSpan span = new ClickableSpan() {
+ @Override
+ public void onClick(@NonNull View widget) {
+ TransitionManager.beginDelayedTransition((ViewGroup) getParent());
+ setMaxLines(nextLines);
+ ExpandableTextView.super.setText(text);
+ }
+ };
+ collapse.setSpan(span, 0, collapse.length(), 0);
+ expand = new SpannableString(context.getString(R.string.expand));
+ expand.setSpan(span, 0, expand.length(), 0);
+ setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
+ @Override
+ public void setText(CharSequence text, BufferType type) {
+ this.text = text;
+ super.setText(text, type);
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ var lineCount = getLayout().getLineCount();
+ if (lineCount > maxLines) {
+ SpannableString s;
+ int end;
+ if (maxLines == getMaxLines()) {
+ nextLines = lineCount + 1;
+ end = getLayout().getLineStart(getMaxLines() - 1);
+ s = expand;
+ } else {
+ nextLines = maxLines;
+ end = text.length();
+ s = collapse;
+ }
+ sb.clearSpans();
+ sb.clear();
+ sb.append(text, 0, end - 1);
+ sb.append("\n");
+ sb.append(s);
+ super.setText(sb, BufferType.NORMAL);
+ }
+ return super.onPreDraw();
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ @Override
+ public boolean onTouchEvent(@NonNull MotionEvent event) {
+ Layout layout = this.getLayout();
+ if (layout != null) {
+ int line = layout.getLineForVertical((int) event.getY());
+ int offset = layout.getOffsetForHorizontal(line, event.getX());
+
+ if (getText() instanceof Spanned) {
+ Spanned spanned = (Spanned) getText();
+
+ ClickableSpan[] links = spanned.getSpans(offset, offset, ClickableSpan.class);
+
+ if (links.length == 0) {
+ super.onTouchEvent(event);
+ return false;
+ }
+ }
+ }
+
+ return super.onTouchEvent(event);
+ }
+
+}
diff --git a/app/src/main/res/layout/item_module.xml b/app/src/main/res/layout/item_module.xml
index af05ce86..3217add6 100644
--- a/app/src/main/res/layout/item_module.xml
+++ b/app/src/main/res/layout/item_module.xml
@@ -35,6 +35,7 @@
android:id="@+id/item_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:animateLayoutChanges="true"
tools:ignore="RtlSymmetry">
- Brown
Grey
Blue grey
+ expand
+ collapse