我正在使用布局(news_headline.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:foo="http://schemas.android.com/apk/res/com.justin.jar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/news_headline_padding" >
<TextView
android:id="@+id/news_headline_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="3"
android:paddingLeft="@dimen/common_left_padding"
android:paddingRight="5dp"
android:textSize="@dimen/news_first_headline_text"
foo:customFont="cabin.medium.ttf"
android:textColor="@color/search_autosuggest_header_text"
android:layout_toLeftOf="@id/news_headline_image" />
<TextView
android:id="@+id/metadata"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/search_autosuggest_item_subtitle"
android:textSize="@dimen/metadata"
android:paddingLeft="@dimen/common_left_padding"
android:paddingRight="5dp"
android:layout_alignLeft="@id/news_headline_text"
android:layout_toLeftOf="@id/news_headline_image"
android:layout_below="@id/news_headline_text"
/>
<ImageView
android:id="@+id/news_headline_image"
android:layout_width="254dp"
android:layout_height="180dp"
android:background="@drawable/container_dropshadow"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:paddingTop="1dp"
android:paddingBottom="1dp"
android:layout_alignParentRight="true"
android:layout_marginLeft="@dimen/common_left_padding"
android:contentDescription="@string/headline_image"
/>
</RelativeLayout>
现在,我打算在布局中添加以下代码块,如文本视图下方所示(我确实尝试过,并且能够无误地运行):
<com.justin.jar.views.LinkableTextView
android:id="@+id/news_body"
foo:customFont="Roboto-Regular.ttf"
android:textSize="@dimen/news_body"
android:lineSpacingExtra="3dp"
android:textColor="@color/article_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
它适用于以下java文件LinkableTextView.java:
public class LinkableTextView extends FontTextView {
private final ArrayList<Hyperlink> mListOfLinks;
private SpannableString mLinkableText;
TextLinkClickListener mListener;
private static final String ARTICLE_REPLACE_STRING = "(Full Story)";
private static final String ARTICLE_PATTERN = "\\[ID:nL\\w+\\]";
private static final String SYMBOL_PATTERN = "<\\S+?>";
private static final String LINK_PATTERN = "(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
public LinkableTextView(final Context context, final AttributeSet attrs) {
super(context, attrs);
mListOfLinks = new ArrayList<Hyperlink>();
}
public LinkableTextView(final Context context, final AttributeSet attrs, final String pattern) {
super(context, attrs);
mListOfLinks = new ArrayList<Hyperlink>();
}
public SpannableString gatherArticleLinks(final String text) {
mListOfLinks.clear();
if (StringUtils.isEmpty(text)) {
return null;
}
mLinkableText = new SpannableString(text);
gatherLinks(mListOfLinks, mLinkableText, ARTICLE_PATTERN);
for (int i = 0; i < mListOfLinks.size(); i++) {
final Hyperlink linkSpec = mListOfLinks.get(i);
mLinkableText.setSpan(linkSpec.span, linkSpec.start, linkSpec.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
setText(mLinkableText);
return mLinkableText;
}
public void setOnTextLinkClickListener(final TextLinkClickListener newListener) {
mListener = newListener;
}
/**
* this method parses the article from start to end looking for three different patterns (Articles, Symbols and Links)
* it will process the first matched pattern first and continue parsing from the end of the last found pattern.
* The process will end when none of the patterns match any more
* @param links
* @param spannable
* @param patternString
*/
private final void gatherLinks(final ArrayList<Hyperlink> links, final Spannable spannable, final String patternString) {
Pattern patternArticle = Pattern.compile(ARTICLE_PATTERN);
Pattern patternSymbol = Pattern.compile(SYMBOL_PATTERN);
Pattern patternLink = Pattern.compile(LINK_PATTERN);
boolean isArticleFinished = false;
boolean isSymbolFinished = false;
boolean isLinkFinished = false;
final Matcher matcherArticle = patternArticle.matcher(spannable);
final Matcher matcherSymbol = patternSymbol.matcher(spannable);
final Matcher matcherLink = patternLink.matcher(spannable);
final StringBuilder articleBuilder = new StringBuilder();
int lastParsedIndex = 0;
while (!isArticleFinished || !isSymbolFinished || !isLinkFinished) {
int startArticle = Integer.MAX_VALUE;
if (!isArticleFinished) {
if (matcherArticle.find(lastParsedIndex)) {
startArticle = matcherArticle.start();
} else {
isArticleFinished = true;
}
}
int startSymbol = Integer.MAX_VALUE;
if (!isSymbolFinished) {
if (matcherSymbol.find(lastParsedIndex)) {
startSymbol = matcherSymbol.start();
} else {
isSymbolFinished = true;
}
}
int startLink = Integer.MAX_VALUE;
if (!isLinkFinished) {
if (matcherLink.find(lastParsedIndex)) {
startLink = matcherLink.start();
} else {
isLinkFinished = true;
}
}
Hyperlink spec = new Hyperlink();
String matchedText;
if (startArticle < startSymbol && startArticle < startLink) { //Article link is first and it will be processed
if (!isArticleFinished) {
int endArticle = matcherArticle.end();
if (startArticle == lastParsedIndex) {
articleBuilder.append(" ");
}
articleBuilder.append(spannable.subSequence(lastParsedIndex, startArticle));
matchedText = spannable.subSequence(startArticle, endArticle).toString();
spec.span = new InternalArticleURLSpan(matchedText);
spec.start = articleBuilder.length();
articleBuilder.append(ARTICLE_REPLACE_STRING);
spec.end = articleBuilder.length();
links.add(spec);
lastParsedIndex = endArticle;
}
} else if (startSymbol < startArticle && startSymbol < startLink) { //Symbol Link is first and it will be processed
if (!isSymbolFinished) {
int endSymbol = matcherSymbol.end();
if (startSymbol == lastParsedIndex) {
articleBuilder.append(" ");
}
articleBuilder.append(spannable.subSequence(lastParsedIndex, startSymbol));
matchedText = spannable.subSequence(startSymbol, endSymbol).toString();
spec.span = new InternalSymbolURLSpan(matchedText);
spec.start = articleBuilder.length();
articleBuilder.append(spec.span.getLinkText(matchedText));
spec.end = articleBuilder.length();
links.add(spec);
lastParsedIndex = endSymbol;
}
} else {
if (!isLinkFinished) { //Http Link is first so it will be processed
int endLink = matcherLink.end();
if (startLink == lastParsedIndex) {
articleBuilder.append(" ");
}
articleBuilder.append(spannable.subSequence(lastParsedIndex, startLink));
matchedText = spannable.subSequence(startLink, endLink).toString();
spec.span = new InternalLinkURLSpan(matchedText);
spec.start = articleBuilder.length();
articleBuilder.append(spec.span.getLinkText(matchedText));
spec.end = articleBuilder.length();
links.add(spec);
lastParsedIndex = endLink;
}
}
}
articleBuilder.append(spannable.subSequence(lastParsedIndex, spannable.length()));
mLinkableText = new SpannableString(articleBuilder.toString());
}
public abstract class InternalURLSpan extends ClickableSpan {
public abstract String getLinkText(final String clickedSpan);
}
public class InternalArticleURLSpan extends InternalURLSpan {
private final String clickedSpan;
private Pattern mPattern;
public InternalArticleURLSpan(final String clickedString) {
setPattern();
clickedSpan = getLinkText(clickedString);
}
@Override
public void onClick(final View textView) {
mListener.onArticleClick(textView, clickedSpan);
}
public String getLinkText(final String clickedSpan) {
if (mPattern != null) {
final Matcher matcher = mPattern.matcher(clickedSpan);
if (matcher.find()) {
return matcher.group();
} else {
throw new IllegalArgumentException("Invalid article ID:" + clickedSpan);
}
}
return null;
}
private void setPattern() {
mPattern = Pattern.compile("\\w+(?=\\])");
}
}
public class InternalSymbolURLSpan extends InternalURLSpan {
private final String clickedSpan;
public InternalSymbolURLSpan(final String clickedString) {
clickedSpan = getLinkText(clickedString);
}
@Override
public void onClick(final View textView) {
mListener.onSymbolClick(textView, clickedSpan);
}
public String getLinkText(final String clickedSpan) {
return clickedSpan.substring(1, clickedSpan.length()-1);
}
}
public class InternalLinkURLSpan extends InternalURLSpan {
private final String clickedSpan;
public InternalLinkURLSpan(final String clickedString) {
clickedSpan = getLinkText(clickedString);
}
@Override
public void onClick(final View textView) {
mListener.onLinkClick(textView, clickedSpan);
}
public String getLinkText(final String clickedSpan) {
return clickedSpan;
}
}
class Hyperlink {
InternalURLSpan span;
int start;
int end;
}
}
但每次我在xml代码中添加该代码块并运行时,它都没有显示任何内容,就像在空白中一样,好像代码从未使用过(代码的其余部分看起来很好)。如何使其可见(注意:它在另一个xml文件中工作正常,这是一个线性布局,并使用整个页面进行信息显示)。
答案 0 :(得分:0)
你必须在RelativeLayout
中提及它的位置,我无法在你的代码中找到,所以如果这是问题,那么请检查它,否则你可以回来找到更具体的问题,以便可能有根据这个来编辑答案的可能性。
在LinearLayout
中它起作用,因为它将元素放在vertical or horizontal orientation
中。但是在RelativeLayout
如果你没有提到它的位置,一个视图会替换另一个视图。这可能是问题所在。
答案 1 :(得分:0)
您只需指定您想要的位置即可。假设您想要metadat
TextView
以下。给它android:layout_below
属性。像这样的东西
<TextView
android:id="@+id/metadata"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/search_autosuggest_item_subtitle"
android:textSize="@dimen/metadata"
android:paddingLeft="@dimen/common_left_padding"
android:paddingRight="5dp"
android:layout_alignLeft="@id/news_headline_text"
android:layout_toLeftOf="@id/news_headline_image"
android:layout_below="@id/news_headline_text"
/>
<com.justin.jar.views.LinkableTextView
android:id="@+id/news_body"
foo:customFont="Roboto-Regular.ttf"
android:textSize="@dimen/news_body"
android:lineSpacingExtra="3dp"
android:textColor="@color/article_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/metadata" /> //this line here
默认情况下,View
中的RelativeLayout
位于左上方,所以如果有其他内容,那么它可能会覆盖此View
而不会在其中提供位置layout
。如果这不能解决你的问题,那么请发布你试图把它放在那里的方式,也许是你想要和/或得到的图片。