如何在我的布局文件中使用以下linkedtextview代码?

时间:2013-11-21 20:48:31

标签: android android-layout android-fragments android-linearlayout textview

我正在使用布局(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文件中工作正常,这是一个线性布局,并使用整个页面进行信息显示)。

2 个答案:

答案 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。如果这不能解决你的问题,那么请发布你试图把它放在那里的方式,也许是你想要和/或得到的图片。