Android:测量动态创建TextView的宽度有时会出错

时间:2016-09-06 09:54:27

标签: android

我遇到了一个奇怪的小问题。

此活动的目标是显示两个文本,一个是原始的,第二个是答案文本。答案文本包含错误,用户必须查找并标记这些错误。 我们提出的解决方案是将文本拆分为单词,并在TextView中将每个单词显示为自己的单词。所有这些TextView都是在运行时动态创建的,因为有许多不同的文本要显示。 有两种情况,我们需要一个'换行符':a)文本包含换行符(
)和b)显示器的宽度不再适合任何文本。

此解决方案大部分时间都有效,但每个文本有2-4个单词,不适合行宽,因此可视化分为多行。

以下是代码:

String[] questionSplit = exercise.exerciseQuestion.split(" ");
ids = new Integer[questionSplit.length];
int displayWidth = getResources().getDisplayMetrics().widthPixels;
int currentLineWidth = 0;
Integer lastIdInRow = 0;
int counter = 0;
for(String bit : questionSplit) {
    TextView tv = new TextView(this);
    tv.setId(generateViewId());
    ids[counter] = tv.getId();

    //Exception for <br>
    if(bit.equals("<br>")) {
        lastIdInRow = ids[counter - 1];
        currentLineWidth = 0;
    } else {
        tv.setText(bit);
        tv.setPadding(dpToPx(3), dpToPx(3), dpToPx(2), dpToPx(2));
        tv.measure(0, 0);
        currentLineWidth += tv.getMeasuredWidth();
        RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

        if(currentLineWidth <= displayWidth && counter == 0) {
            // move along, nothing to see here
        } else if(currentLineWidth <= displayWidth && counter != 0) {
            p.addRule(RelativeLayout.RIGHT_OF, ids[counter - 1]);
        } else {
            lastIdInRow = ids[counter - 1];
            currentLineWidth = 0;
        }

        if(lastIdInRow != 0 && lastIdInRow != tv.getId()) {
            p.addRule(RelativeLayout.BELOW, lastIdInRow);
        }

        rlTextComparisonOriginal.addView(tv,p);
    }

    counter++;
}

解释TextViews的布局规则:如果measuredWidth适合该行,则添加RIGHT_OF最后一个id规则。如果它会溢出,则添加行规则中的最后一个ID。 正如我之前提到的,对于大多数完美运行的文本。但是有一些词不适合。如果我将displayWidth更改为仅显示宽度的80%,则错误仅保留单词更改,因此我认为它不是特定的文本/单词。

这是视图的相关部分xml

<ScrollView
    android:id="@+id/svTextComparisonDesc"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/tvTextComparisonHeaderMiddle"
    android:paddingBottom="55dp"
    >
    <RelativeLayout
        android:id="@+id/rlTextComparison"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/tvTextComparisonDescription"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:background="@color/text_background"
            android:padding="10dp"
            android:text="@string/text_exercise_desription"
            android:textSize="@dimen/activity_text_description_size"
            android:scrollHorizontally="false"
            />
        <RelativeLayout
            android:id="@+id/rlTextComparisonOriginal"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@color/text_background"
            android:layout_below="@id/tvTextComparisonDescription"
            />
        <RelativeLayout
            android:id="@+id/rlTextComparisonAnswer"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/rlTextComparisonOriginal"
            />

    </RelativeLayout>
</ScrollView>

最后一点信息:现在上面的代码位于活动的onCreate方法中。如果我记录了measuredWidth和displayWidth以及currentWidth,逻辑没有被破坏,则measuredWidth适合于该行,但是在渲染之后,它并没有。

任何想法实际上可能是什么问题?提前谢谢!

使用上面提到的lib后,代码更清晰,看起来像这样:

//Exception for <br>
if(bit.equals("<br>")) {
    FlowLayout.LayoutParams lp = new FlowLayout.LayoutParams(0,0);
    lp.setNewLine(true);
    flTextComparisonOriginal.addView(tv,lp);
} else {
    tv.setText(bit);
    tv.setPadding(dpToPx(3), dpToPx(3), dpToPx(2), dpToPx(2));
    RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    flTextComparisonOriginal.addView(tv, p);
}

2 个答案:

答案 0 :(得分:1)

如果使用库是可以接受的而不是自己编码,你会在关键字&#34; FlowLayout&#34;下的github上找到两个项目。这听起来像是解决了你需要的布局:

https://github.com/ApmeM/android-flowlayout

https://github.com/blazsolar/FlowLayout

答案 1 :(得分:0)

要获取文本视图的宽度和高度,

Sub copy_pic_excel()
Dim xlsobj_2 As Object
Dim xlsfile_chart As Object
Dim chart As Object

Set xlsobj_2 = CreateObject("Excel.Application")
xlsobj_2.Application.Visible = False
Set xlsfile_chart = xlsobj_2.Application.Workbooks.Open("C:\Users\Kiel\Desktop\chart.xls")

Set chart = xlsfile_chart.Charts("chart1")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

Set chart = xlsfile_chart.Charts("chart2")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

Set chart = xlsfile_chart.Charts("chart3")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

 Set chart = xlsfile_chart.Charts("chart4")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

Set chart = xlsfile_chart.Charts("chart5")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

Set chart = xlsfile_chart.Charts("chart6")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

Set chart = xlsfile_chart.Charts("chart7")
chart.Select
chart.ChartArea.Copy
With Selection
   .PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
        Placement:=wdInLine, DisplayAsIcon:=False
End With

'clean up
Set xlsfile_chart = Nothing
xlsobj_2.Quit
Set xlsobj_2 = Nothing
End Sub