I managed to fixed this issue in one on my old projects. The idea is to make some preprocessing on the text first so as to be able to have only bullets delimiters inside the text, assuming in your case the bullet delimiter is "- " according to the text above. Then extract each bullet line and render it using the BulletSpan (https://developer.android.com/reference/android/text/style/BulletSpan) or if you need more customization for rendering your own Bullet you can use the LeadingMarginSpan (https://developer.android.com/reference/android/text/style/LeadingMarginSpan) which offers you the flexibility to draw a custom bullet point using its drawLeadingMargin method. In my case i made the below Bullet Util class:
public class BulletUtil {
public enum BulletStyle{
Style1("•", "\u2022"),
Style2("●", "\u25CF"),
Style3("○", "\u25CB"),
Style4("▪", "\u25AA"),
Style5("■", "\u25A0"),
Style6("□", "\u25A1"),
Style7("►", "\u25BA");
private String symbol;
private String code;
private BulletStyle(String symbol, String code){
this.symbol = symbol;
this.code = code;
}
public String getCode() {
return code;
}
}
/**
* Creates Leading Margin Spans {@link LeadingMarginSpan} based on a gap width and a color integer.*
* @param originText the original Text
* @param bulletDelimiter the bullet delimiter
* @param bulletGapWidth the distance, in pixels, between the bullet point and the paragraph.
* @param bulletColor the bullet point color, as a color integer.
* @param bulletStyle the bullet style
* @return CharSequence with BulletSpans
*/
public static CharSequence addLeadingBullets(String originText, String bulletDelimiter, int bulletGapWidth, @ColorInt int bulletColor, BulletStyle bulletStyle) {
return createLeadingMarginSpans(bulletGapWidth, bulletColor, getBulletList(originText, bulletDelimiter), bulletStyle);
}
/**
* Creates Bullet Spans {@link BulletSpan} based on a gap width and a color integer.*
* @param originText the original Text
* @param bulletDelimiter the bullet delimiter
* @param bulletGapWidth the distance, in pixels, between the bullet point and the paragraph.
* @param bulletColor the bullet point color, as a color integer.
* @return CharSequence with BulletSpans
*/
public static CharSequence addBullets(String originText, String bulletDelimiter, int bulletGapWidth, @ColorInt int bulletColor) {
return createBulletSpans(bulletGapWidth, bulletColor, getBulletList(originText, bulletDelimiter));
}
/**
* Retrieves Bullet List based on a Bullet Delimiter
* @param text the Text
* @param bulletDelimiter the bullet delimiter
* @return List<String> the bullet List
*/
public static List<String> getBulletList(String text, String bulletDelimiter){
List<String> bulletLines = Arrays.asList(text.split(bulletDelimiter));
List<String> bulletList = new ArrayList<>();
if(bulletLines!=null && bulletLines.size()>0){
for(int i=0; i<bulletLines.size(); i++){
String bulletLine = bulletLines.get(i);
if(!TextUtils.isEmpty(bulletLine)){
bulletList.add(bulletLine);
}
}
}
return bulletList;
}
/**
* Creates Bullet Spans {@link BulletSpan} based on a gap width and a color integer.
*
* @param bulletGapWidth the distance, in pixels, between the bullet point and the paragraph.
* @param bulletColor the bullet point color, as a color integer.
* @param bulletList the bullet List lines
*/
public static CharSequence createBulletSpans(int bulletGapWidth, @ColorInt int bulletColor, @NonNull List<String> bulletList) {
SpannableStringBuilder sbb = new SpannableStringBuilder();
for(int i=0; i<bulletList.size(); i++){
CharSequence bulletLine = bulletList.get(i) + (i < bulletList.size()-1 ? "\n" : "");
Spannable spannable = new SpannableString(bulletLine);
BulletSpan bulletSpan = new BulletSpan(bulletGapWidth, bulletColor);
spannable.setSpan(bulletSpan, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
sbb.append(spannable);
}
return sbb;
}
/**
* Creates Bullet LeadingMarginSpans {@link LeadingMarginSpan} based on a gap width and a color integer.
*
* @param bulletGapWidth the distance, in pixels, between the bullet point and the paragraph.
* @param bulletColor the bullet point color, as a color integer.
* @param bulletList the bullet List lines
* @param bulletStyle the bullet enum Style
*/
public static CharSequence createLeadingMarginSpans(int bulletGapWidth, @ColorInt int bulletColor, @NonNull List<String> bulletList, BulletStyle bulletStyle) {
SpannableStringBuilder sbb = new SpannableStringBuilder();
for(int i=0; i<bulletList.size(); i++){
CharSequence bulletLine = bulletList.get(i) + (i < bulletList.size()-1 ? "\n" : "");
Spannable spannable = new SpannableString(bulletLine);
String bulletPointStyle = bulletStyle.getCode();
LeadingMarginSpan bulletLeadingMarginSpan = new LeadingMarginSpan()
{
@Override
public int getLeadingMargin(boolean first) {
return bulletPointStyle.length()*bulletGapWidth;
}
@Override
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
if (first) {
Paint.Style orgStyle = p.getStyle();
p.setStyle(Paint.Style.FILL);
p.setColor(bulletColor);
c.drawText(bulletPointStyle + " ", 0, bottom - p.descent(), p);
p.setColor(Color.BLACK);
p.setStyle(orgStyle);
}
}
};
spannable.setSpan(bulletLeadingMarginSpan, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
sbb.append(spannable);
}
return sbb;
}
}
and i am calling it like below using BulletSpan:
String text = "- Enhanced base performance. - Lightweight headband enhances comfort and adds durability - Easy to adjust headband ensures optimum fit and comfort - 2 metre-long cable";
bulletTextView.setText(BulletUtil.addBullets(text, "- ", 100, getResources().getColor(android.R.color.holo_red_dark)));
or using LeadingMarginSpan:
String text = "- Enhanced base performance. - Lightweight headband enhances comfort and adds durability - Easy to adjust headband ensures optimum fit and comfort - 2 metre-long cable";
bulletTextView.setText(BulletUtil.addLeadingBullets(text, "- ", 100, getResources().getColor(android.R.color.black), BulletUtil.BulletStyle.Style2));
i have used your sample data in the above examples.