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