1

I'm trying to display a bunch of text on the screen by placing TextViews inside rows of single-line LinearLayouts. Each word is stored in its own separate TextView, and I want to be able to place as many TextViews as will fit on a single LinearLayout line and detect when I've run out of horizontal space so that I can move to the next line.

The problem I'm facing is that I can't seem to find a way to measure the changing layout sizes as I create the display, because I can't get a reference width using getWidth() on the parent layout, and even after I add the TextViews, I can't seem to control the width.

We had a working version before, but it did everything using on hard-coded numbers based on the number of characters in a TextView at a fixed size. I'm trying to extend the app to work with all text and screen sizes. If this needs to be completely overhauled, I understand - I just want to be able to fill up the screen with an indefinite number of lines of text.

An obvious solution would be to just place all the text inside one TextView, but we need to be able to access each Word/Ponctuation object and its attributes through the displayed TextViews.

// layout_row is the current LinearLayout row I'm adding my TextViews to
// layout is the LinearLayout parent of all layout_rows
// text.text_content is a linked list of Word and Ponctuation objects
// each Word and Ponctuation object has a TextView attribute called view

private void display_views() {

    if (text != null)
    {
        boolean prochainLigneSuivante; // if new line is to follow
        int widthSoFar = 0;
        int layoutWidth = layout_row.getWidth();  

        for (Object o : text.text_content) {
            if (o instanceof Word ) {
                Word w = (Word) o;
                Object next = text.next(o);

                if  (noNeedForSpace(w)) {
                    // by default all TextViews have 
                    // right padding to simulate spaces
                    w.view.setPadding(0, 0, 0, 0);
                }

                layout_row.addView(w.view);
                widthSoFar += w.view.getWidth();

                // Am I out of space?
                prochainLigneSuivante = widthSoFar >= layoutWidth;

                if(prochainLigneSuivante) {
                    layout_row.removeView(w.view);
                    widthSoFar = 0;
                    layout_row = new LinearLayout(context);
                    layout_row.setOrientation(LinearLayout.HORIZONTAL);
                    layout_row.addView(w.view);
                    layout_row.setBackgroundColor(Color.BLACK);
                    layout_row.setLayoutParams(new 
                        LayoutParams(LayoutParams.WRAP_CONTENT, 
                            LayoutParams.MATCH_PARENT));
                    layout.addView(layout_row);     
                }
            }
            else if (o instanceof Ponctuation) {
                Ponctuation p = (Ponctuation) o;

                if (p.text.contains("CR")) {
                    layout_row = new LinearLayout(context);
                    layout_row.setOrientation(LinearLayout.HORIZONTAL); 
                    layout_row.setLayoutParams(new 
                            LayoutParams(LayoutParams.WRAP_CONTENT, 
                                        LayoutParams.MATCH_PARENT));
                    widthSoFar = 0;
                    layout.addView(layout_row);
                }
                else {
                    if (p.view.getText().equals(" "))
                        p.view.setPadding(0, 0, 0, 0);
                    layout_row.addView(p.view);
                    if(!p.view.getText().equals(""))
                    widthSoFar += p.view.getWidth();
                }
            }
        }
    }
    else {
        Log.e("Text", "text est nul");
    }


    scroll.refreshDrawableState();
    transition.startTransition(0);

}
bibismcbryde
  • 369
  • 1
  • 5
  • 17
  • Creating a TextView for each word is quite inefficient, is there a specific need for that? If it is for text formatting, you can use `Html.fromHtml` to get basic html styles (bold, italics, etc.) – nicopico Feb 05 '13 at 16:42
  • Unfortunately, there is a need for each word to be in a separate TextView. We need to be able to change the background and color of each word separately, as well as access attributes of the Word/Ponctuation objects. Would that be possible with SpannableStrings in a single TextView? – bibismcbryde Feb 05 '13 at 16:58
  • You can surely change background and text color with `SpannableString`. To get Word/Ponctuation objects associated with a span though, you might be able to use a SparseArray with the word position as index? – nicopico Feb 05 '13 at 22:40
  • Thanks - I'm messing with that right now. If I were to continue with this idea, do you know if it is possible to determine the screen location of a substring, perhaps given its index, within the TextView? (I'm finding nothing so far.) That's originally why we had separate row layouts as "lines" of text, because we want to be able to scroll the screen to whatever word we might be focusing on. – bibismcbryde Feb 06 '13 at 16:36
  • Actually hold that thought - just found this to find a SpannableString http://stackoverflow.com/questions/11905486/how-get-coordinate-of-a-clickablespan-inside-a-textview – bibismcbryde Feb 06 '13 at 16:40

0 Answers0