2

I've got a slightly complicated layout, containing several custom-views that each calculate how much space they need and whatnot. At the top of this layout, I've got a TextView which is supposed to count down from say.. 02:04:20 (hh:mm:ss), and update every second.

My problem is not updating the text, the problem is that when I DO update the text, ALL of the views in my layout gets re-drawn.. Also, I'm using a gallery in this layout, so when interacting with the gallery while the text is updated makes the gallery switch INSTANTLY to the place you've selected (even though you're in the middle of switching to a new item in the gallery).

So.. How to update the textview without making other views re-draw?

NinjaLama
  • 43
  • 1
  • 7
  • You need to show your layout file and the code where the text is getting updated. – a.ch. Feb 21 '12 at 09:49
  • I'd have to post a lot then. I've solved the problem by subclassing SurfaceView and draw the text manually. I was aware I could do this from the beginning, but I was hoping I could do what I wanted to do with just a normal TextView :/ – NinjaLama Feb 21 '12 at 21:45

1 Answers1

7

The TextView won't invalidate the entire layout on setText() if the view's width is fixed and the height of the view won't change. Change the layout parameter android:layout_width from "wrap_content" to a fixed width like "fill_parent" or "100sp".

Source:

/**
 * Check whether entirely new text requires a new view layout
 * or merely a new text layout.
 */

private void checkForRelayout() {
    // If we have a fixed width, we can just swap in a new text layout
    // if the text height stays the same or if the view height is fixed.

    if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT ||
            (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth)) &&
            (mHint == null || mHintLayout != null) &&
            (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {
        // Static width, so try making a new text layout.

        int oldht = mLayout.getHeight();
        int want = mLayout.getWidth();
        int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();

        /*
         * No need to bring the text into view, since the size is not
         * changing (unless we do the requestLayout(), in which case it
         * will happen at measure).
         */
        makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
                      mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
                      false);

        if (mEllipsize != TextUtils.TruncateAt.MARQUEE) {
            // In a fixed-height view, so use our new text layout.
            if (mLayoutParams.height != LayoutParams.WRAP_CONTENT &&
                mLayoutParams.height != LayoutParams.MATCH_PARENT) {
                invalidate();
                return;
            }

            // Dynamic height, but height has stayed the same,
            // so use our new text layout.
            if (mLayout.getHeight() == oldht &&
                (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
                invalidate();
                return;
            }
        }

        // We lose: the height has changed and we have a dynamic height.
        // Request a new view layout using our new text layout.
        requestLayout();
        invalidate();
    } else {
        // Dynamic width, so we have no choice but to request a new
        // view layout with a new text layout.

        nullLayouts();
        requestLayout();
        invalidate();
    }
}
Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
user1552631
  • 71
  • 1
  • 2
  • In addition to that, as the source code shows, avoid setting the ellipsize property to marquee. Removing that property that was set by error on a TextView used as a time counter driven by a SeekBar caused a significant performance improvement. If the layout has a ListView as well, a full relayout causes some unnecessary bindView() calls that affects performance. – DavGin Oct 11 '13 at 15:16