Apply monocles read more read less feature
This commit is contained in:
parent
100db3898a
commit
dcb2bb5d35
9 changed files with 305 additions and 4 deletions
|
@ -1136,7 +1136,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
viewHolder.indicator = view.findViewById(R.id.security_indicator);
|
||||
viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
|
||||
viewHolder.image = view.findViewById(R.id.message_image);
|
||||
viewHolder.messageBody = view.findViewById(R.id.message_body);
|
||||
if (activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
|
||||
viewHolder.messageBody = view.findViewById(R.id.message_body_collapsable);
|
||||
} else if (!activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
|
||||
viewHolder.messageBody = view.findViewById(R.id.message_body);
|
||||
}
|
||||
viewHolder.time = view.findViewById(R.id.message_time);
|
||||
viewHolder.subject = view.findViewById(R.id.message_subject);
|
||||
viewHolder.inReplyTo = view.findViewById(R.id.in_reply_to);
|
||||
|
@ -1160,7 +1164,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
viewHolder.indicator = view.findViewById(R.id.security_indicator);
|
||||
viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
|
||||
viewHolder.image = view.findViewById(R.id.message_image);
|
||||
viewHolder.messageBody = view.findViewById(R.id.message_body);
|
||||
if (activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
|
||||
viewHolder.messageBody = view.findViewById(R.id.message_body_collapsable);
|
||||
} else if (!activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
|
||||
viewHolder.messageBody = view.findViewById(R.id.message_body);
|
||||
}
|
||||
viewHolder.time = view.findViewById(R.id.message_time);
|
||||
viewHolder.subject = view.findViewById(R.id.message_subject);
|
||||
viewHolder.inReplyTo = view.findViewById(R.id.in_reply_to);
|
||||
|
|
|
@ -135,7 +135,11 @@
|
|||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Photo"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
<de.monocles.chat.ReadMoreTextView
|
||||
app:trimExpandedText="@string/show_less"
|
||||
app:trimCollapsedText="@string/show_more"
|
||||
app:trimMode="trimModeLength"
|
||||
app:colorClickableText="?colorPrimary"
|
||||
android:id="@+id/context_preview_text"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -65,7 +65,23 @@
|
|||
android:paddingTop="4dp"
|
||||
android:autoLink="web"
|
||||
android:longClickable="false"
|
||||
android:textAppearance="?textAppearanceBodyMedium" />
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
android:visibility="gone" />
|
||||
|
||||
<de.monocles.chat.ReadMoreTextView
|
||||
app:trimExpandedText="@string/show_less"
|
||||
app:trimCollapsedText="@string/show_more"
|
||||
app:trimMode="trimModeLength"
|
||||
app:colorClickableText="?colorPrimary"
|
||||
android:id="@+id/message_body_collapsable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:paddingTop="4dp"
|
||||
android:autoLink="web"
|
||||
android:longClickable="false"
|
||||
android:textAppearance="?textAppearanceBodyMedium"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_button"
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
<bool name="show_thread_feature">false</bool>
|
||||
<bool name="show_maps_inside">true</bool>
|
||||
<bool name="show_own_accounts">false</bool>
|
||||
<bool name="set_text_collapsable">false</bool>
|
||||
</resources>
|
||||
|
|
|
@ -1114,4 +1114,8 @@
|
|||
<string name="pref_show_mappreview_inside_summary">Load a preview of maps for a share location inside the chat</string>
|
||||
<string name="pref_show_own_accounts">Show own account name</string>
|
||||
<string name="pref_show_own_accounts_summary">Shows the used account on messages overview and details</string>
|
||||
<string name="pref_set_text_collapsable_summary">Collapses text with more than 230 signs</string>
|
||||
<string name="pref_set_text_collapsable">Collapse long text</string>
|
||||
<string name="show_less">... show less</string>
|
||||
<string name="show_more">... show more</string>
|
||||
</resources>
|
||||
|
|
|
@ -117,6 +117,12 @@
|
|||
android:entryValues="@array/avatars_shape_values"
|
||||
android:summary="@string/pref_avatar_shape_summary"
|
||||
android:title="@string/pref_avatars_shape" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="@bool/set_text_collapsable"
|
||||
android:icon="@drawable/ic_keyboard_double_arrow_down_24dp"
|
||||
android:key="set_text_collapsable"
|
||||
android:summary="@string/pref_set_text_collapsable_summary"
|
||||
android:title="@string/pref_set_text_collapsable" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="@bool/use_green_background"
|
||||
android:icon="@drawable/ic_forum_24dp"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package de.monocles.chat;
|
||||
|
||||
/**
|
||||
* Created by Mays Atari.
|
||||
*/
|
||||
|
||||
public interface ReadMoreListener {
|
||||
void onReadMoreClick(boolean readMore);
|
||||
}
|
239
src/monocleschat/java/de/monocles/chat/ReadMoreTextView.java
Normal file
239
src/monocleschat/java/de/monocles/chat/ReadMoreTextView.java
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Borja Bravo
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.monocles.chat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextPaint;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
|
||||
public class ReadMoreTextView extends AppCompatTextView {
|
||||
|
||||
private static final int TRIM_MODE_LINES = 0;
|
||||
private static final int TRIM_MODE_LENGTH = 1;
|
||||
private static final int DEFAULT_TRIM_LENGTH = 230;
|
||||
private static final int DEFAULT_TRIM_LINES = 7;
|
||||
private static final int INVALID_END_INDEX = -1;
|
||||
private static final boolean DEFAULT_SHOW_TRIM_EXPANDED_TEXT = true;
|
||||
private static final boolean DEFAULT_READ_MORE = true;
|
||||
private static final String ELLIPSIZE = "... ";
|
||||
|
||||
private CharSequence text;
|
||||
private BufferType bufferType;
|
||||
private boolean readMore;
|
||||
private int trimLength;
|
||||
private CharSequence trimCollapsedText;
|
||||
private CharSequence trimExpandedText;
|
||||
private final ReadMoreClickableSpan viewMoreSpan;
|
||||
private int colorClickableText;
|
||||
private final boolean showTrimExpandedText;
|
||||
private ReadMoreListener readMoreListener;
|
||||
|
||||
private int trimMode;
|
||||
private int lineEndIndex;
|
||||
private int trimLines;
|
||||
|
||||
public ReadMoreTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ReadMoreTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ReadMoreTextView);
|
||||
this.trimLength = typedArray.getInt(R.styleable.ReadMoreTextView_trimLength, DEFAULT_TRIM_LENGTH);
|
||||
int resourceIdTrimCollapsedText =
|
||||
typedArray.getResourceId(R.styleable.ReadMoreTextView_trimCollapsedText, R.string.show_more);
|
||||
int resourceIdTrimExpandedText =
|
||||
typedArray.getResourceId(R.styleable.ReadMoreTextView_trimExpandedText, R.string.show_less);
|
||||
this.trimCollapsedText = getResources().getString(resourceIdTrimCollapsedText);
|
||||
this.trimExpandedText = getResources().getString(resourceIdTrimExpandedText);
|
||||
this.trimLines = typedArray.getInt(R.styleable.ReadMoreTextView_trimLines, DEFAULT_TRIM_LINES);
|
||||
this.colorClickableText = typedArray.getColor(R.styleable.ReadMoreTextView_colorClickableText,
|
||||
ContextCompat.getColor(context, androidx.appcompat.R.color.abc_btn_colored_borderless_text_material));
|
||||
this.showTrimExpandedText =
|
||||
typedArray.getBoolean(R.styleable.ReadMoreTextView_showTrimExpandedText, DEFAULT_SHOW_TRIM_EXPANDED_TEXT);
|
||||
this.readMore = typedArray.getBoolean(R.styleable.ReadMoreTextView_readMore, DEFAULT_READ_MORE);
|
||||
this.trimMode = typedArray.getInt(R.styleable.ReadMoreTextView_trimMode, TRIM_MODE_LINES);
|
||||
typedArray.recycle();
|
||||
viewMoreSpan = new ReadMoreClickableSpan();
|
||||
onGlobalLayoutLineEndIndex();
|
||||
setText();
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
super.setText(text, bufferType);
|
||||
super.setText(getDisplayableText(), bufferType);
|
||||
setMovementMethod(LinkMovementMethod.getInstance());
|
||||
setHighlightColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
private CharSequence getDisplayableText() {
|
||||
return getTrimmedText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(CharSequence text, BufferType type) {
|
||||
this.text = text;
|
||||
bufferType = type;
|
||||
setText();
|
||||
}
|
||||
|
||||
private CharSequence getTrimmedText(CharSequence text) {
|
||||
if (trimMode == TRIM_MODE_LENGTH) {
|
||||
if (text != null && text.length() > trimLength) {
|
||||
if (readMore) {
|
||||
return updateCollapsedText();
|
||||
} else {
|
||||
return updateExpandedText();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trimMode == TRIM_MODE_LINES) {
|
||||
if (text != null && lineEndIndex > 0) {
|
||||
if (readMore) {
|
||||
if (getLayout().getLineCount() > trimLines) {
|
||||
return updateCollapsedText();
|
||||
}
|
||||
} else {
|
||||
return updateExpandedText();
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private CharSequence updateCollapsedText() {
|
||||
int trimEndIndex = text.length();
|
||||
switch (trimMode) {
|
||||
case TRIM_MODE_LINES:
|
||||
trimEndIndex = lineEndIndex - (ELLIPSIZE.length() + trimCollapsedText.length() + 1);
|
||||
if (trimEndIndex < 0) {
|
||||
trimEndIndex = trimLength + 1;
|
||||
}
|
||||
break;
|
||||
case TRIM_MODE_LENGTH:
|
||||
trimEndIndex = trimLength + 1;
|
||||
break;
|
||||
}
|
||||
SpannableStringBuilder s = new SpannableStringBuilder(text, 0, trimEndIndex)
|
||||
.append(ELLIPSIZE)
|
||||
.append(trimCollapsedText);
|
||||
return addClickableSpan(s, trimCollapsedText);
|
||||
}
|
||||
|
||||
private CharSequence updateExpandedText() {
|
||||
if (showTrimExpandedText) {
|
||||
SpannableStringBuilder s = new SpannableStringBuilder(text, 0, text.length()).append(trimExpandedText);
|
||||
return addClickableSpan(s, trimExpandedText);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private CharSequence addClickableSpan(SpannableStringBuilder s, CharSequence trimText) {
|
||||
s.setSpan(viewMoreSpan, s.length() - trimText.length(), s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return s;
|
||||
}
|
||||
|
||||
public void setTrimLength(int trimLength) {
|
||||
this.trimLength = trimLength;
|
||||
setText();
|
||||
}
|
||||
|
||||
public void setColorClickableText(int colorClickableText) {
|
||||
this.colorClickableText = colorClickableText;
|
||||
}
|
||||
|
||||
public void setTrimCollapsedText(CharSequence trimCollapsedText) {
|
||||
this.trimCollapsedText = trimCollapsedText;
|
||||
}
|
||||
|
||||
public void setTrimExpandedText(CharSequence trimExpandedText) {
|
||||
this.trimExpandedText = trimExpandedText;
|
||||
}
|
||||
|
||||
public void setTrimMode(int trimMode) {
|
||||
this.trimMode = trimMode;
|
||||
}
|
||||
|
||||
public void setTrimLines(int trimLines) {
|
||||
this.trimLines = trimLines;
|
||||
}
|
||||
|
||||
public void setReadMore(boolean readMore) {
|
||||
this.readMore = readMore;
|
||||
}
|
||||
|
||||
public void setReadMoreListener(ReadMoreListener readMoreListener) {
|
||||
this.readMoreListener = readMoreListener;
|
||||
}
|
||||
|
||||
private class ReadMoreClickableSpan extends ClickableSpan {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
readMore = !readMore;
|
||||
setText();
|
||||
|
||||
if(readMoreListener != null){
|
||||
readMoreListener.onReadMoreClick(readMore);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
ds.setColor(colorClickableText);
|
||||
}
|
||||
}
|
||||
|
||||
private void onGlobalLayoutLineEndIndex() {
|
||||
if (trimMode == TRIM_MODE_LINES) {
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
ViewTreeObserver obs = getViewTreeObserver();
|
||||
obs.removeOnGlobalLayoutListener(this);
|
||||
refreshLineEndIndex();
|
||||
setText();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshLineEndIndex() {
|
||||
try {
|
||||
if (trimLines == 0) {
|
||||
lineEndIndex = getLayout().getLineEnd(0);
|
||||
} else if (trimLines > 0 && getLineCount() >= trimLines) {
|
||||
lineEndIndex = getLayout().getLineEnd(trimLines - 1);
|
||||
} else {
|
||||
lineEndIndex = INVALID_END_INDEX;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,4 +10,18 @@
|
|||
<attr name="ic_accounts_selected" format="reference" />
|
||||
<attr name="ic_group_unselected" format="reference" />
|
||||
<attr name="ic_group_selected" format="reference" />
|
||||
|
||||
<declare-styleable name="ReadMoreTextView">
|
||||
<attr name="trimExpandedText" format="string" />
|
||||
<attr name="trimCollapsedText" format="string" />
|
||||
<attr name="trimLength" format="integer" />
|
||||
<attr name="showTrimExpandedText" format="boolean" />
|
||||
<attr name="readMore" format="boolean" />
|
||||
<attr name="colorClickableText" format="color" />
|
||||
<attr name="trimLines" format="integer" />
|
||||
<attr name="trimMode">
|
||||
<enum name="trimModeLine" value="0"/>
|
||||
<enum name="trimModeLength" value="1"/>
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
|
Loading…
Add table
Reference in a new issue