来自原始文件的文本在图像周围流动

Text coming from a raw file flowing around an image

这是我的第一个问题。 我正在尝试开发一个带有文本和图像的 "book",但我在显示文本(从原始文件加载)流动和文本视图中的图像时遇到问题。 我试过 this 并且在字符串资源中定义文本时它工作正常。但是,当文本来自外部文件(例如,包含换行符的 .txt 文件)时,TextView 看起来像这样:

---------  text text text text text 
|       |  text text text text text 
---------  text text text text text 
text text text text 
text text text text
text text text text
text text text text

也就是说,在图片之后,每一行都在右边留下一个与图片大小相同的空space。

我不知道为什么会这样,我是不是漏掉了什么?这是代码:

ImageView page_im_iv = (ImageView) findViewById(R.id.page_image);
TextView page_text = (TextView) findViewById(R.id.page_text);

Drawable page_image getResources().getDrawable(R.drawable.anyname);
page_im_iv.setBackground(page_image);

float left_margin = page_image.getIntrinsicWidth() + 10;
float top_margin = page_image.getIntrinsicHeight() + 10;

float flines = top_margin/page_text.getTextSize();
int ilines = (int) flines;

StringBuilder raw_text = readRaw(this,res_id);//res_id changes dynamically, it is just the name of the .txt file

SpannableString ss = new SpannableString(raw_text.toString());
ss.setSpan(new MyLeadingMarginSpan2(ilines, left_margin), 0, ss.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

page_text.setText(ss);

这是布局:

<ScrollView  xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="example.ActivityBookPage"
xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

        <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">


          <ImageView
          android:id="@+id/page_image"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"/>


          <TextView
          android:id="@+id/page_text"
          android:layout_width="wrap_content"
          android:layout_height="match_parent"
          android:layout_marginBottom="10dp"/>


      </RelativeLayout>

    <!-- Other stuff 
    ...
    -->
     </LinearLayout>
</ScrollView >

就这些了。

如果问题出在 readRaw 方法上,代码如下:

public static StringBuilder readRaw(Context ctx,int res_id) {

        StringBuilder text = new StringBuilder();
        InputStream is = ctx.getResources().openRawResource(res_id);
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr, 8192);

        try {
            String line;
            while ((line = br.readLine()) != null)  {
                text.append(line);
                text.append("\n");

            }
            isr.close();
            is.close();
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return text;
    }

这是 MyLeadingMarginSpan2 class 的代码,从之前的 link

复制粘贴而来
public class MyLeadingMarginSpan2 implements LeadingMarginSpan2 {
    private int margin;
    private int lines;

    public MyLeadingMarginSpan2(int lines, int margin) {
        this.margin = margin;
        this.lines = lines;
    }

    @Override
    public int getLeadingMargin(boolean first) {
        return first ? margin : 0;
    }

    @Override
    public int getLeadingMarginLineCount() {
        return lines;
    }

    @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) {}
}

终于找到解决办法了(感谢this老回复)。问题是来自原始文件的文本可能包含换行符 (\n),计算 "ilines" 时未考虑这些换行符。因此,我们需要计算刚好适合图像右侧的字符数,然后包括一个新的换行符,然后是文本的其余部分。这是代码

int charCount = page_text_layout.getLineEnd(Math.min(ilines - 1, page_text_layout.getLineCount() - 1));//see below what page_text_layout is
//in case the image is big enough to have all 
//the text at its right, just use ss.length as 
//the third parameter for setSpan   
if (charCount >= ss.length() || charCount <= 0 ) {
            ss.setSpan(new MyLeadingMarginSpan2(ilines, left_margin), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                            page_text.setText(ss);                
}  
else { //in case the text is longer, make three blocks
            Spannable s1 = new SpannableStringBuilder(ss, 0, charCount);
            s1.setSpan(new MyLeadingMarginSpan2(ilines, left_margin), 0, charCount, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            Spannable s2 = new SpannableStringBuilder(System.getProperty("line.separator"));
            Spannable s3 = new SpannableStringBuilder(ss, charCount, ss.length());
            page_text.setText(TextUtils.concat(s1, s2, s3));
}

其中 page_text_layout 之前在 onGlobalLayout 回调中定义(在我的例子中是在 onCreate() 方法中):

ViewTreeObserver vto = page_text.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
               page_text_layout = page_text.getLayout();  
            }
        });

当然可以改进此代码(例如,检查 s1 是否在单词中间打断文本),但这将是主要结构。

希望这对某人有所帮助!