Skip to content

Commit 0fd2fe5

Browse files
yunkongdeskid
authored andcommitted
fix: fix issue #24, #22, #17
1 parent 2563203 commit 0fd2fe5

5 files changed

Lines changed: 149 additions & 13 deletions

File tree

app/src/main/java/com/borjabravo/readmoretextviewsample/MainActivity.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
package com.borjabravo.readmoretextviewsample;
22

3+
import android.content.Context;
34
import android.os.Bundle;
45
import android.support.v7.app.AppCompatActivity;
6+
import android.support.v7.widget.LinearLayoutManager;
7+
import android.support.v7.widget.RecyclerView;
8+
import android.view.LayoutInflater;
9+
import android.view.View;
10+
import android.view.ViewGroup;
511
import android.widget.TextView;
12+
import android.widget.Toast;
613

714
public class MainActivity extends AppCompatActivity {
815

@@ -18,5 +25,47 @@ protected void onCreate(Bundle savedInstanceState) {
1825
text3.setText(getString(R.string.lorem_ipsum3));
1926
TextView text4 = findViewById(R.id.text4);
2027
text4.setText(getString(R.string.one_line_text));
28+
RecyclerView listView = (RecyclerView) findViewById(R.id.list);
29+
listView.setLayoutManager(new LinearLayoutManager(this));
30+
listView.setAdapter(new ItemAdapter());
31+
}
32+
33+
static class ItemAdapter extends RecyclerView.Adapter<ViewHolder> {
34+
35+
@Override
36+
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
37+
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
38+
return new ViewHolder(view);
39+
}
40+
41+
@Override
42+
public void onBindViewHolder(ViewHolder holder, final int position) {
43+
final Context context = holder.itemView.getContext();
44+
holder.text.setText(context.getString(R.string.lorem_ipsum));
45+
holder.itemView.setOnClickListener(new View.OnClickListener() {
46+
@Override
47+
public void onClick(View v) {
48+
Toast.makeText(context, "you clicked " + position, Toast.LENGTH_SHORT).show();
49+
}
50+
});
51+
52+
//todo ReadMoreTextView should have a pulbic method to reset textView's collapse status
53+
// e.g.
54+
//((ReadMoreTextView) holder.itemView).setCollapsed(position % 2 == 0)
55+
}
56+
57+
@Override
58+
public int getItemCount() {
59+
return 10;
60+
}
61+
}
62+
63+
static class ViewHolder extends RecyclerView.ViewHolder {
64+
TextView text;
65+
66+
public ViewHolder(View itemView) {
67+
super(itemView);
68+
text = (TextView) itemView.findViewById(R.id.text);
69+
}
2170
}
2271
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<shape xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:shape="rectangle">
4+
<solid android:color="@android:color/transparent" />
5+
<corners android:radius="6px" />
6+
<stroke
7+
android:width="2px"
8+
android:color="#66666666" />
9+
</shape>

app/src/main/res/layout/activity_main.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,10 @@
3737
android:layout_height="wrap_content"
3838
/>
3939

40+
<android.support.v7.widget.RecyclerView
41+
android:id="@+id/list"
42+
android:layout_width="match_parent"
43+
android:layout_height="wrap_content" />
44+
45+
4046
</LinearLayout>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:layout_width="match_parent"
5+
android:layout_height="wrap_content"
6+
android:layout_margin="4dp"
7+
android:background="@drawable/round_btn_bg"
8+
android:orientation="vertical">
9+
10+
<com.borjabravo.readmoretextview.ReadMoreTextView
11+
android:id="@+id/text"
12+
android:layout_width="wrap_content"
13+
android:layout_height="wrap_content"
14+
app:trimCollapsedText="@string/show_all_content"
15+
app:trimLines="5" />
16+
</LinearLayout>

readmoretextview/src/main/java/com/borjabravo/readmoretextview/ReadMoreTextView.java

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@
1818
import android.content.Context;
1919
import android.content.res.TypedArray;
2020
import android.graphics.Color;
21-
import android.os.Build;
2221
import android.support.v4.content.ContextCompat;
22+
import android.text.Layout;
23+
import android.text.Selection;
24+
import android.text.Spannable;
2325
import android.text.SpannableStringBuilder;
2426
import android.text.Spanned;
2527
import android.text.TextPaint;
26-
import android.text.method.LinkMovementMethod;
2728
import android.text.style.ClickableSpan;
2829
import android.util.AttributeSet;
30+
import android.view.MotionEvent;
2931
import android.view.View;
3032
import android.view.ViewTreeObserver;
3133
import android.widget.TextView;
@@ -76,13 +78,56 @@ public ReadMoreTextView(Context context, AttributeSet attrs) {
7678
this.trimMode = typedArray.getInt(R.styleable.ReadMoreTextView_trimMode, TRIM_MODE_LINES);
7779
typedArray.recycle();
7880
viewMoreSpan = new ReadMoreClickableSpan();
81+
setOnTouchListener(new OnTouchListener() {
82+
@Override
83+
public boolean onTouch(View v, MotionEvent event) {
84+
TextView widget = (TextView) v;
85+
Spannable buffer = Spannable.Factory.getInstance().newSpannable(widget.getText());
86+
int action = event.getAction();
87+
88+
// https://stackoverflow.com/questions/8558732/listview-textview-with-linkmovementmethod-makes-list-item-unclickable
89+
90+
// to fix a bug when call setMovementMethod will make list item unclickable
91+
if (action == MotionEvent.ACTION_UP ||
92+
action == MotionEvent.ACTION_DOWN) {
93+
int x = (int) event.getX();
94+
int y = (int) event.getY();
95+
96+
x -= widget.getTotalPaddingLeft();
97+
y -= widget.getTotalPaddingTop();
98+
99+
x += widget.getScrollX();
100+
y += widget.getScrollY();
101+
102+
Layout layout = widget.getLayout();
103+
int line = layout.getLineForVertical(y);
104+
int off = layout.getOffsetForHorizontal(line, x);
105+
106+
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
107+
108+
if (link.length != 0) {
109+
if (action == MotionEvent.ACTION_UP) {
110+
link[0].onClick(widget);
111+
} else if (action == MotionEvent.ACTION_DOWN) {
112+
Selection.setSelection(buffer,
113+
buffer.getSpanStart(link[0]),
114+
buffer.getSpanEnd(link[0]));
115+
}
116+
117+
return true;
118+
} else {
119+
Selection.removeSelection(buffer);
120+
}
121+
}
122+
return false;
123+
}
124+
});
79125
onGlobalLayoutLineEndIndex();
80126
setText();
81127
}
82128

83129
private void setText() {
84130
super.setText(getDisplayableText(), bufferType);
85-
setMovementMethod(LinkMovementMethod.getInstance());
86131
setHighlightColor(Color.TRANSPARENT);
87132
}
88133

@@ -125,7 +170,15 @@ private CharSequence updateCollapsedText() {
125170
int trimEndIndex = text.length();
126171
switch (trimMode) {
127172
case TRIM_MODE_LINES:
128-
trimEndIndex = lineEndIndex - (ELLIPSIZE.length() + trimCollapsedText.length() + 1);
173+
trimEndIndex = lineEndIndex;
174+
//find enough space to layout ELLIPSIZE
175+
float ellipsizeWidth = getPaint().measureText(ELLIPSIZE + trimCollapsedText);
176+
float collapsedWidth = getPaint().measureText(text.subSequence(trimEndIndex, trimEndIndex + 1).toString());
177+
while (collapsedWidth < ellipsizeWidth) {
178+
--trimEndIndex;
179+
collapsedWidth += getPaint().measureText(text.subSequence(trimEndIndex, trimEndIndex + 1).toString());
180+
}
181+
129182
if (trimEndIndex < 0) {
130183
trimEndIndex = trimLength + 1;
131184
}
@@ -193,28 +246,31 @@ public void updateDrawState(TextPaint ds) {
193246

194247
private void onGlobalLayoutLineEndIndex() {
195248
if (trimMode == TRIM_MODE_LINES) {
196-
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
249+
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
197250
@Override
198-
public void onGlobalLayout() {
251+
public boolean onPreDraw() {
199252
ViewTreeObserver obs = getViewTreeObserver();
200-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
201-
obs.removeOnGlobalLayoutListener(this);
202-
} else {
203-
obs.removeGlobalOnLayoutListener(this);
204-
}
253+
obs.removeOnPreDrawListener(this);
205254
refreshLineEndIndex();
206255
setText();
256+
return true;
207257
}
208258
});
209259
}
210260
}
211261

262+
@Override
263+
public boolean performLongClick() {
264+
//a side affect that every slide move will trigger a long click event
265+
return false;
266+
}
267+
212268
private void refreshLineEndIndex() {
213269
try {
214270
if (trimLines == 0) {
215-
lineEndIndex = getLayout().getLineEnd(0);
271+
lineEndIndex = getLayout().getLineVisibleEnd(0);
216272
} else if (trimLines > 0 && getLineCount() >= trimLines) {
217-
lineEndIndex = getLayout().getLineEnd(trimLines - 1);
273+
lineEndIndex = getLayout().getLineVisibleEnd(trimLines - 1);
218274
} else {
219275
lineEndIndex = INVALID_END_INDEX;
220276
}

0 commit comments

Comments
 (0)