diff --git a/app/src/main/java/com/gh/common/view/ExpandTextView.java b/app/src/main/java/com/gh/common/view/ExpandTextView.java index 3a91d80fbc..c7e2c3c15d 100644 --- a/app/src/main/java/com/gh/common/view/ExpandTextView.java +++ b/app/src/main/java/com/gh/common/view/ExpandTextView.java @@ -8,7 +8,6 @@ import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextPaint; -import android.text.style.BackgroundColorSpan; import android.text.style.ClickableSpan; import android.util.AttributeSet; import android.view.View; @@ -23,13 +22,15 @@ public class ExpandTextView extends AppCompatTextView { private CharSequence mSnapshotText; - private String mExpendText = "...全文"; - private int expandTextBackgroundColor = Color.TRANSPARENT; + private String mEndText = "..."; + private String mExpandText = mEndText + "全文"; + private boolean mUseGradientAlphaEndText = false; + private int mExpandTextBackgroundColor = Color.TRANSPARENT; private int mMaxLines = 3; // 由于sdk版本限制(getMaxLines) 这里设置默认值 private boolean mInitLayout = false; - private boolean mOpenLayout = false; + private boolean mIsExpanded = false; // 位于 recyclerView 时需要自行在外层管理是否已展开 private ExpandCallback mExpandCallback; @@ -42,24 +43,26 @@ public class ExpandTextView extends AppCompatTextView { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mMaxLines = getMaxLines(); } - TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView); - mExpendText = array.getString(R.styleable.ExpandTextView_expandText) == null ? mExpendText : array.getString(R.styleable.ExpandTextView_expandText); - expandTextBackgroundColor = array.getColor(R.styleable.ExpandTextView_expandTextBackgroundColor, expandTextBackgroundColor); - array.recycle(); + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView); + mUseGradientAlphaEndText = ta.getBoolean(R.styleable.ExpandTextView_useGradientAlphaEndText, false); + mEndText = ta.getString(R.styleable.ExpandTextView_endText) == null ? mEndText : ta.getString(R.styleable.ExpandTextView_endText); + mExpandText = ta.getString(R.styleable.ExpandTextView_expandText) == null ? mExpandText : ta.getString(R.styleable.ExpandTextView_expandText); + mExpandTextBackgroundColor = ta.getColor(R.styleable.ExpandTextView_expandTextBackgroundColor, mExpandTextBackgroundColor); + ta.recycle(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - if (mInitLayout && !mOpenLayout && getLineCount() > mMaxLines) { + if (mInitLayout && !mIsExpanded && getLineCount() > mMaxLines) { mSnapshotText = getText(); mInitLayout = false; - showExpendButton(); + showExpandButton(); } } public void setExpendText(String text) { - this.mExpendText = text; + this.mExpandText = text; } public void setExpandCallback(ExpandCallback callback) { @@ -72,7 +75,9 @@ public class ExpandTextView extends AppCompatTextView { super.setText(text, type); } - private void showExpendButton() { + private void showExpandButton() { + String finalEndText = ""; + Layout layout = getLayout(); int start = layout.getLineStart(0); int lastLineEnd = layout.getLineEnd(mMaxLines - 1); @@ -80,28 +85,51 @@ public class ExpandTextView extends AppCompatTextView { float lastLineRight = layout.getLineRight(mMaxLines - 1); int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft(); + int additionalEndTextCount = 0; TextPaint paint = getPaint(); - float expendTextWidth = paint.measureText(mExpendText); + float expandTextWidth; + if (mUseGradientAlphaEndText) { + additionalEndTextCount = 2; + expandTextWidth = paint.measureText(mEndText + mExpandText); + } else { + expandTextWidth = paint.measureText(mExpandText); + } + CharSequence content = mSnapshotText.subSequence(start, lastLineEnd); - if (viewWidth - lastLineRight > expendTextWidth) { - content = content.toString().trim() + mExpendText; + + if (viewWidth - lastLineRight > expandTextWidth) { + // TODO 可能最后一行只有一个字符,这里的 -ADDITIONAL_END_TEXT_COUNT 有隐藏问题 + if (mUseGradientAlphaEndText) { + finalEndText = content.toString().substring(content.length() - additionalEndTextCount, content.length()) + mEndText; + content = content.subSequence(0, content.length() - additionalEndTextCount) + finalEndText + mExpandText; + } else { + content = content.toString().trim() + mExpandText; + } } else { CharSequence lastText = mSnapshotText.subSequence(lastLineStart, lastLineEnd); for (int i = lastText.length() - 1; i > 0; i--) { CharSequence sequence = lastText.subSequence(0, i); float w = paint.measureText(sequence.toString()); - if (viewWidth - w - DisplayUtils.dip2px(5) > expendTextWidth) { - content = mSnapshotText.subSequence(start, lastLineStart + i) + mExpendText; + if (viewWidth - w - DisplayUtils.dip2px(5) > expandTextWidth) { + if (mUseGradientAlphaEndText) { + finalEndText = lastText.subSequence(i - additionalEndTextCount, i) + mEndText; + content = mSnapshotText.subSequence(start, lastLineStart + i - additionalEndTextCount) + finalEndText + mExpandText; + } else { + content = mSnapshotText.subSequence(start, lastLineStart + i) + mExpandText; + } break; } } } + SpannableStringBuilder msp = new SpannableStringBuilder(mSnapshotText); int length = msp.length(); - int startPosition = content.length() - mExpendText.length(); - startPosition = startPosition < 0 ? 0 : startPosition; - msp.replace(startPosition, length, mExpendText); + int startPosition = 0; + startPosition = content.length() - finalEndText.length() - mExpandText.length(); + startPosition = Math.max(startPosition, 0); + msp.replace(startPosition, length, finalEndText + mExpandText); + msp.setSpan(new ClickableSpan() { @Override public void updateDrawState(TextPaint ds) { @@ -112,7 +140,7 @@ public class ExpandTextView extends AppCompatTextView { @Override public void onClick(View widget) { - mOpenLayout = true; + mIsExpanded = true; setMaxLines(Integer.MAX_VALUE); setText(mSnapshotText); @@ -120,15 +148,21 @@ public class ExpandTextView extends AppCompatTextView { mExpandCallback.onExpand(); } } - }, startPosition + 3, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - msp.setSpan(new BackgroundColorSpan(expandTextBackgroundColor), startPosition, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + }, startPosition + mEndText.length(), msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + msp.setSpan(new GradientAlphaTextSpan(), startPosition, startPosition + finalEndText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); setText(msp); setMovementMethod(CustomLinkMovementMethod.getInstance()); } + /** + * 此方法仅更改标记,不做实际展开的操作 + */ + public void setIsExpanded(boolean isExpanded) { + mIsExpanded = isExpanded; + } - public void setExpendMaxLines(int maxLines) { + public void setExpandMaxLines(int maxLines) { mMaxLines = maxLines; setMaxLines(maxLines); } diff --git a/app/src/main/java/com/gh/common/view/GradientAlphaTextSpan.kt b/app/src/main/java/com/gh/common/view/GradientAlphaTextSpan.kt new file mode 100644 index 0000000000..8b4e67b574 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/GradientAlphaTextSpan.kt @@ -0,0 +1,32 @@ +package com.gh.common.view + +import android.graphics.Canvas +import android.graphics.LinearGradient +import android.graphics.Paint +import android.graphics.Shader +import android.text.style.ReplacementSpan +import androidx.core.graphics.ColorUtils + +class GradientAlphaTextSpan() : ReplacementSpan() { + + override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int { + return paint.measureText(text, start, end).toInt() + } + + override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) { + val originalColor = paint.color + val originalColorWithAlphaChanged = ColorUtils.setAlphaComponent(paint.color, 1) + + val textWidth = paint.measureText(text, start, end).toInt() + + val mShader = LinearGradient(x, 0F, x + textWidth - 10, 0F, + originalColor, originalColorWithAlphaChanged, Shader.TileMode.CLAMP) + paint.shader = mShader + + canvas.drawText(text, start, end, x, y.toFloat(), paint) + + paint.shader = null + paint.color = originalColor + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt index 4f5d9670da..70ff869bb9 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/desc/DescAdapter.kt @@ -52,13 +52,8 @@ class DescAdapter(context: Context, var descItemList = arrayListOf() - private var mIsIntroExpanded = false - private var mExpandSparseBooleanArray = SparseBooleanArray() - // 是不是第一次 layout ,决定是否显示展开按钮 - private var mIsIntroFirstTimeLayout = true - fun updateDescItemList(descItemList: ArrayList) { this.descItemList = descItemList notifyDataSetChanged() @@ -207,11 +202,11 @@ class DescAdapter(context: Context, private fun bindCustomColumnViewHolder(viewHolder: GameDetailCustomColumnViewHolder, detailEntity: DetailEntity) { val customColumn = detailEntity.customColumn!! val tags = if (customColumn.showInfoTag == true) customColumn.infoTag else arrayListOf() + val maxDesLines = if (mExpandSparseBooleanArray.get(viewHolder.adapterPosition)) Int.MAX_VALUE else customColumn.showDesRowNum!! viewHolder.binding.titleHintTv.paint?.isUnderlineText = true - viewHolder.binding.contentTv.setExpendMaxLines(customColumn.showDesRowNum ?: 3) - - // TODO 记录展开情况 + viewHolder.binding.contentTv.setExpandMaxLines(maxDesLines) + viewHolder.binding.contentTv.setIsExpanded(Int.MAX_VALUE == maxDesLines) viewHolder.binding.customColumn = customColumn viewHolder.binding.shouldBoundToNextItem = detailEntity.shouldBoundTogetherWithNextItem viewHolder.binding.shouldBoundToPreviousItem = detailEntity.shouldBoundTogetherWithPreviousItem @@ -234,6 +229,7 @@ class DescAdapter(context: Context, (viewHolder.binding.recyclerview.adapter as GameDetailCustomColumnAdapter) .updateData(ArrayList(tags!!), customColumn.showInfoTagDes ?: false) viewHolder.binding.contentTv.setExpandCallback { + mExpandSparseBooleanArray.put(viewHolder.adapterPosition, true) if (customColumn.name == "游戏简介") { MtaHelper.onEvent("游戏详情_新", "展开游戏介绍", gameName) } else { diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt index 7d09989fa7..1906500e30 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/rating/RatingReplyAdapter.kt @@ -237,7 +237,7 @@ class RatingReplyAdapter(context: Context, holder.setContent(commentData, viewModel.game, position, entrance, path) holder.binding.run { line.visibility = View.GONE - content.setExpendMaxLines(Int.MAX_VALUE) + content.setExpandMaxLines(Int.MAX_VALUE) comment.setOnClickListener { replyCallback.invoke(null) } diff --git a/app/src/main/res/layout/gamedetail_item_custom_column.xml b/app/src/main/res/layout/gamedetail_item_custom_column.xml index e65070d1c8..66cb2c5d84 100644 --- a/app/src/main/res/layout/gamedetail_item_custom_column.xml +++ b/app/src/main/res/layout/gamedetail_item_custom_column.xml @@ -188,7 +188,9 @@ android:text="@{customColumn.des}" android:textColor="@color/text_666666" android:textSize="12sp" - app:expandText="... 全部" + app:useGradientAlphaEndText="true" + app:endText="... " + app:expandText="全部" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/contentHintContainer" diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 0a60d436fc..572574774e 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -103,7 +103,9 @@ + +