Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions app/src/main/java/com/devs/readmoreoptiondemo/MyAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static class ViewHolder extends RecyclerView.ViewHolder {

MyAdapter(Context context) {
this.context = context;
readMoreOption = new ReadMoreOption.Builder(context)
readMoreOption = new ReadMoreOption.Builder(context).textLength(3,ReadMoreOption.TYPE_LINE)
.build();
}

Expand All @@ -62,10 +62,13 @@ public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (position % 2 == 0) {
readMoreOption.addReadMoreTo(holder.mTextView, Html.fromHtml(context.getString(R.string.dummy_text)));
} else {
readMoreOption.addReadMoreTo(holder.mTextView, Html.fromHtml(context.getString(R.string.dummy_text)).toString());
if (position % 3 == 0) {
readMoreOption.addReadMoreTo(holder.mTextView, Html.fromHtml(context.getString(R.string.dummy_html_text)));
} else if (position % 2 == 0) {
readMoreOption.addReadMoreTo(holder.mTextView, Html.fromHtml(context.getString(R.string.dummy_html_text_with_new_line)).toString());
}else{

readMoreOption.addReadMoreTo(holder.mTextView, context.getString(R.string.dummy_normal_text_with_new_line));
}
}

Expand Down
6 changes: 5 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@

<resources>
<string name="app_name">ReadMoreOption</string>
<string name="dummy_text"> <![CDATA[ <b>Lorem</b> <i>Ipsum</i> is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.]]></string>
<string name="dummy_html_text"> <![CDATA[<br><br><br> <b>Lorem</b> <i>Ipsum</i> is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.]]></string>
<string name="dummy_html_text_with_new_line"> <![CDATA[<b>Lorem</b> <i>Ipsum</i> <br><br><br> is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.]]></string>
<string name="dummy_normal_text_with_new_line"> \n\n\nLorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</string>


</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.devs.readmoreoption;

import android.animation.LayoutTransition;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.text.Spannable;
import android.text.SpannableString;
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.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
Expand All @@ -36,11 +33,9 @@
* Created by ${Deven} on 6/1/18.
*/
public class ReadMoreOption {

private static final String TAG = ReadMoreOption.class.getSimpleName();
public static final int TYPE_LINE = 1;
public static final int TYPE_CHARACTER = 2;

private static final String TAG = ReadMoreOption.class.getSimpleName();
// required
private Context context;
// optional
Expand All @@ -53,7 +48,7 @@ public class ReadMoreOption {
private boolean labelUnderLine;
private boolean expandAnimation;

private ReadMoreOption(Builder builder){
private ReadMoreOption(Builder builder) {
this.context = builder.context;
this.textLength = builder.textLength;
this.textLengthType = builder.textLengthType;
Expand All @@ -65,65 +60,75 @@ private ReadMoreOption(Builder builder){
this.expandAnimation = builder.expandAnimation;
}

public void addReadMoreTo(final TextView textView, final CharSequence text){
if(textLengthType==TYPE_CHARACTER) {
public void addReadMoreTo(final TextView textView, final CharSequence text) {
if (textLengthType == TYPE_CHARACTER) {
if (text.length() <= textLength) {
textView.setText(text);
return;
}
}
else {
} else {
// If TYPE_LINE
textView.setLines(textLength);
textView.setText(text);
}

textView.post(new Runnable() {
@Override
public void run() {

int textLengthNew = textLength;

if(textLengthType==TYPE_LINE) {


SpannableStringBuilder spannableStringBuilder;
if (textLengthType == TYPE_LINE) {
if (textView.getLayout().getLineCount() <= textLength) {
textView.setText(text);
return;
}

ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) textView.getLayoutParams();

String subString = text.toString().substring(textView.getLayout().getLineStart(0),
textView.getLayout().getLineEnd(textLength - 1));
textLengthNew = subString.length() - (moreLabel.length()+4+(lp.rightMargin/6));
//get start index for last line
final int startIndex = textView.getLayout().getLineStart(textLength - 1);
//get end index for last line
final int endIndex = textView.getLayout().getLineEnd(textLength - 1);
//check char count for last line
final int charCount = endIndex - startIndex;
//more label length
int moreLabelLength = (moreLabel.length() + 4 + lp.rightMargin / 6);
//check if char count is greater than or equals more label length.
if (charCount >= moreLabelLength) {
//get substring for no of max lines and append more label
CharSequence subString = text.subSequence(textView.getLayout().getLineStart(0),
textView.getLayout().getLineEnd(textLength - 1));
textLengthNew = subString.length() - (moreLabel.length() + 4 + lp.rightMargin / 6);
} else {
//get substring for ( no of max lines - 1)
CharSequence subString = text.subSequence(textView.getLayout().getLineStart(0),
textView.getLayout().getLineStart(textLength - 1));
textLengthNew = subString.length();
}
}

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text.subSequence(0, textLengthNew))

//get subsequence for given length and append label
spannableStringBuilder = new SpannableStringBuilder(text.subSequence(0, textLengthNew))
.append("...")
.append(moreLabel);

SpannableString ss = SpannableString.valueOf(spannableStringBuilder);
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View view) {
addReadLess(textView, text);
}

@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(labelUnderLine);
ds.setColor(moreLabelColor);
}
};
ss.setSpan(clickableSpan, ss.length() - moreLabel.length(), ss.length() , Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

ss.setSpan(clickableSpan, ss.length() - moreLabel.length(), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && expandAnimation) {
LayoutTransition layoutTransition = new LayoutTransition();
layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
((ViewGroup)textView.getParent()).setLayoutTransition(layoutTransition);
((ViewGroup) textView.getParent()).setLayoutTransition(layoutTransition);
}

textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
Expand All @@ -132,12 +137,9 @@ public void updateDrawState(TextPaint ds) {

private void addReadLess(final TextView textView, final CharSequence text) {
textView.setMaxLines(Integer.MAX_VALUE);

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text)
.append(lessLabel);

SpannableString ss = SpannableString.valueOf(spannableStringBuilder);

ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View view) {
Expand All @@ -148,14 +150,15 @@ public void run() {
}
});
}

@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(labelUnderLine);
ds.setColor(lessLabelColor);
}
};
ss.setSpan(clickableSpan, ss.length() - lessLabel.length(), ss.length() , Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(clickableSpan, ss.length() - lessLabel.length(), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());
}
Expand All @@ -169,48 +172,48 @@ public static class Builder {
private String moreLabel = "read more";
private String lessLabel = "read less";
private int moreLabelColor = Color.parseColor("#ff00ff");
private int lessLabelColor = Color.parseColor("#ff00ff");
private int lessLabelColor = Color.parseColor("#ff00ff");
private boolean labelUnderLine = false;
private boolean expandAnimation = false;

public Builder(Context context){
public Builder(Context context) {
this.context = context;
}

/**
* @param length can be no. of line OR no. of characters - default is 100 character
* @param length can be no. of line OR no. of characters - default is 100 character
* @param textLengthType ReadMoreOption.TYPE_LINE for no. of line OR
* ReadMoreOption.TYPE_CHARACTER for no. of character
* - default is ReadMoreOption.TYPE_CHARACTER
* @return Builder obj
*/
public Builder textLength(int length, int textLengthType){
public Builder textLength(int length, int textLengthType) {
this.textLength = length;
this.textLengthType = textLengthType;
return this;
}

public Builder moreLabel(String moreLabel){
public Builder moreLabel(String moreLabel) {
this.moreLabel = moreLabel;
return this;
}

public Builder lessLabel(String lessLabel){
public Builder lessLabel(String lessLabel) {
this.lessLabel = lessLabel;
return this;
}

public Builder moreLabelColor(int moreLabelColor){
public Builder moreLabelColor(int moreLabelColor) {
this.moreLabelColor = moreLabelColor;
return this;
}

public Builder lessLabelColor(int lessLabelColor){
public Builder lessLabelColor(int lessLabelColor) {
this.lessLabelColor = lessLabelColor;
return this;
}

public Builder labelUnderLine(boolean labelUnderLine){
public Builder labelUnderLine(boolean labelUnderLine) {
this.labelUnderLine = labelUnderLine;
return this;
}
Expand All @@ -220,15 +223,13 @@ public Builder labelUnderLine(boolean labelUnderLine){
* - default is false
* @return Builder obj
*/
public Builder expandAnimation(boolean expandAnimation){
public Builder expandAnimation(boolean expandAnimation) {
this.expandAnimation = expandAnimation;
return this;
}

public ReadMoreOption build(){
public ReadMoreOption build() {
return new ReadMoreOption(this);
}

}

}