কোডটির মাধ্যমে প্রতিবার পাঠের অংশগুলি রঙ করতে চাই যা আমি আমার সমস্ত অ্যাপ্লিকেশনগুলিতে অনেক কিছু করে যাচ্ছি (এবং যেহেতু কোনও ক্ষেত্রে পাঠ্যটি বিভিন্ন ইনলাইন- সহ রানটাইম সেট করা হচ্ছে) প্রত্যেকবার কোডের মাধ্যমে এটি করার ধারণাটি আমি পছন্দ করি না- সংজ্ঞায়িত রং) তাই আমি নিজের তৈরি করেছি MarkableTextView
।
ধারণাটি ছিল:
- স্ট্রিং থেকে এক্সএমএল ট্যাগগুলি সনাক্ত করুন
- ট্যাগ নামটি সনাক্ত করুন এবং ম্যাচ করুন
- বৈশিষ্ট্য এবং পাঠ্যের অবস্থানটি এক্সট্রাক্ট এবং সেভ করুন
- ট্যাগ সরান এবং সামগ্রী রাখুন
- বৈশিষ্ট্যগুলির মাধ্যমে আইট্রেট করুন এবং স্টাইলগুলি প্রয়োগ করুন
প্রক্রিয়াটি ধাপে ধাপে এখানে:
প্রথমে একটি প্রদত্ত স্ট্রিংয়ে এক্সএমএল ট্যাগগুলি সন্ধান করার জন্য আমার একটি উপায়ের প্রয়োজন ছিল এবং Regex
কৌশলটি করেছিলেন ..
<([a-zA-Z]+(?:-[a-zA-Z0-9]+)*)(?:\s+([^>]*))?>([^>][^<]*)</\1\s*>
উপরের একটি এক্সএমএল ট্যাগ মেলে এটির জন্য নিম্নলিখিত মানদণ্ড থাকতে হবে:
- বৈধ ট্যাগ নাম
<a>
<a >
<a-a>
<a ..attrs..>
কিন্তু না< a>
<1>
- বন্ধ থাকা ট্যাগটির সাথে মিল রয়েছে
<a></a>
তবে এর মতো মিল রয়েছে<a></b>
- কোনও বিষয়বস্তু, যেহেতু "কিছুই" স্টাইল করার দরকার নেই
বৈশিষ্ট্যগুলির জন্য আমরা এটি ব্যবহার করতে যাচ্ছি ..
([a-zA-Z]+)\s*=\s*(['"])\s*([^'"]+?)\s*\2
এটির একই ধারণা রয়েছে এবং সাধারণত আমার উভয়ের পক্ষে বেশিদূর যাওয়ার দরকার নেই যেহেতু সংকলকটি যদি বিন্যাসের বাইরে চলে যায় তবে বাকী যত্ন নেবে।
এখন আমাদের এমন একটি শ্রেণি দরকার যা উত্তোলিত ডেটা ধরে রাখতে পারে:
public class MarkableSheet {
private String attributes;
private String content;
private int outset;
private int ending;
private int offset;
private int contentLength;
public MarkableSheet(String attributes, String content, int outset, int ending, int offset, int contentLength) {
this.attributes = attributes;
this.content = content;
this.outset = outset;
this.ending = ending;
this.offset = offset;
this.contentLength = contentLength;
}
public String getAttributes() {
return attributes;
}
public String getContent() {
return content;
}
public int getOutset() {
return outset;
}
public int getContentLength() {
return contentLength;
}
public int getEnding() {
return ending;
}
public int getOffset() {
return offset;
}
}
অন্য কিছুর আগে, আমরা এই শীতল পুনরুক্তি যুক্ত করতে যাচ্ছি যা আমি দীর্ঘকাল ধরে ম্যাচের মধ্য দিয়ে লুপ করতে ব্যবহার করেছি (লেখকের স্মরণ করতে পারি না) :
public static Iterable<MatchResult> matches(final Pattern p, final CharSequence input) {
return new Iterable<MatchResult>() {
public Iterator<MatchResult> iterator() {
return new Iterator<MatchResult>() {
final Matcher matcher = p.matcher(input);
MatchResult pending;
public boolean hasNext() {
if (pending == null && matcher.find()) {
pending = matcher.toMatchResult();
}
return pending != null;
}
public MatchResult next() {
if (!hasNext()) { throw new NoSuchElementException(); }
MatchResult next = pending;
pending = null;
return next;
}
public void remove() { throw new UnsupportedOperationException(); }
};
}
};
}
চিহ্নিতযোগ্য পাঠ্য ভিউ:
public class MarkableTextView extends AppCompatTextView {
public MarkableTextView(Context context) {
super(context);
}
public MarkableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MarkableTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setText(CharSequence text, BufferType type) {
text = prepareText(text.toString());
super.setText(text, type);
}
public Spannable Markable;
private Spannable prepareText(String text) {
String parcel = text;
Multimap<String, MarkableSheet> markableSheets = ArrayListMultimap.create();
int totalOffset = 0;
for (MatchResult match : matches(Markable.Patterns.XML, parcel)) {
String tag = match.group(1);
if (!tag.equals(Markable.Tags.MARKABLE)) {
break;
}
String attributes = match.group(2);
String content = match.group(3);
int outset = match.start(0);
int ending = match.end(0);
int offset = totalOffset;
int contentLength = match.group(3).length();
totalOffset = (ending - outset) - contentLength;
MarkableSheet sheet =
new MarkableSheet(attributes, content, outset, ending, offset, contentLength);
markableSheets.put(tag, sheet);
Matcher reMatcher = Markable.Patterns.XML.matcher(parcel);
parcel = reMatcher.replaceFirst(content);
}
Markable = new SpannableString(parcel);
for (MarkableSheet sheet : markableSheets.values()) {
for (MatchResult match : matches(Markable.Patterns.ATTRIBUTES, sheet.getAttributes())) {
String attribute = match.group(1);
String value = match.group(3);
stylate(attribute,
value,
sheet.getOutset(),
sheet.getOffset(),
sheet.getContentLength());
}
}
return Markable;
}
শেষ অবধি, স্টাইলিং, সুতরাং আমি এই উত্তরের জন্য তৈরি একটি খুব সাধারণ স্টাইলার এখানে:
public void stylate(String attribute, String value, int outset, int offset, int length) {
outset -= offset;
length += outset;
if (attribute.equals(Markable.Tags.TEXT_STYLE)) {
if (value.contains(Markable.Tags.BOLD) && value.contains(Markable.Tags.ITALIC)) {
Markable.setSpan(
new StyleSpan(Typeface.BOLD_ITALIC),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (value.contains(Markable.Tags.BOLD)) {
Markable.setSpan(
new StyleSpan(Typeface.BOLD),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (value.contains(Markable.Tags.ITALIC)) {
Markable.setSpan(
new StyleSpan(Typeface.ITALIC),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (value.contains(Markable.Tags.UNDERLINE)) {
Markable.setSpan(
new UnderlineSpan(),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
if (attribute.equals(Markable.Tags.TEXT_COLOR)) {
if (value.equals(Markable.Tags.ATTENTION)) {
Markable.setSpan(
new ForegroundColorSpan(ContextCompat.getColor(
getContext(),
R.color.colorAttention)),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
else if (value.equals(Markable.Tags.INTERACTION)) {
Markable.setSpan(
new ForegroundColorSpan(ContextCompat.getColor(
getContext(),
R.color.colorInteraction)),
outset,
length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
Markable
সংজ্ঞাযুক্ত শ্রেণিটি এখানে কেমন দেখাচ্ছে তা এখানে:
public class Markable {
public static class Patterns {
public static final Pattern XML =
Pattern.compile("<([a-zA-Z]+(?:-[a-zA-Z0-9]+)*)(?:\\s+([^>]*))?>([^>][^<]*)</\\1\\s*>");
public static final Pattern ATTRIBUTES =
Pattern.compile("(\\S+)\\s*=\\s*(['\"])\\s*(.+?)\\s*\\2");
}
public static class Tags {
public static final String MARKABLE = "markable";
public static final String TEXT_STYLE = "textStyle";
public static final String BOLD = "bold";
public static final String ITALIC = "italic";
public static final String UNDERLINE = "underline";
public static final String TEXT_COLOR = "textColor";
public static final String ATTENTION = "attention";
public static final String INTERACTION = "interaction";
}
}
আমাদের এখন যা দরকার তা হ'ল একটি স্ট্রিংয়ের রেফারেন্স করা এবং মূলত এটির মতো দেখতে হবে:
<string name="markable_string">
<![CDATA[Hello <markable textStyle=\"underline\" textColor=\"interaction\">world</markable>!]]>
</string>
একটি সঙ্গে ট্যাগ মোড়ানো নিশ্চিত করুন CDATA Section
পালায় "
সঙ্গে \
।
আমি এটি অযথা কোড স্টাফিংয়ের প্রয়োজন ছাড়াই সমস্ত বিভিন্ন উপায়ে পাঠ্যের অংশগুলি প্রক্রিয়া করার একটি মডুলার সমাধান হিসাবে তৈরি করেছি।