tags:

views:

9353

answers:

3

Hi

I am using a custom title view in my application for each activity. In one of the activities, based on button clicks I need to change the custom title view. Now this works fine every time when I make a call to setFeatureInt.

But if I try to update any items in the custom title (say change the text of a button or a text view on the title), the update does not take place.

Debugging through the code shows that the text view and button instances are not null and I can also see the custom title bar. But the text on the text view or the button is not updated. Has anyone else faced this problem? How do I resolve it?

Thanks.

EDIT

Here's what I tried. Does not get updated even on calling postInvalidate.

    getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.text_title);

 TextView databar = (TextView) findViewById(R.id.title_text);
 databar.setText("Some Text");
 databar.postInvalidate();

 Button leftButton = (Button) findViewById(R.id.left_btn);
 leftButton.setOnClickListener(mLeftListener);
 leftButton.setText("Left Btn");
 leftButton.postInvalidate();

 Button rightBtn = (Button) findViewById(R.id.right_btn);
 rightBtn.setOnClickListener(mRightListener);
 rightBtn.postInvalidate();
A: 

Are you calling invalidate or postInvalidate to redraw the view after updating the text? If it's a custom View, can you put a breakpoint in the draw code to make sure it's getting called?

If you're on the UI thread, you can call 'invalidate' if you're not, you must call 'postInvalidate' or the view won't redraw itself.

haseman
If it helps, the view is redrawn coz I see the updated title bar but the controls on the title bar don't change
lostInTransit
+7  A: 

The problem is that the only Window implementation (PhoneWindow) uses a LayoutInflater in its setFeatureInt method and instantiates the new layout with inflate and attachToRoot=true. Consequently, when you call setFeatureInt, the new layouts are not replaced but attached to the internal title container and thus drawn on top of each other.

You can workaround this by using the following helper method instead of setFeatureInt. The helper simply removes all views from the internal title container before the new custom title feature is set:


private void setCustomTitleFeatureInt(int value) {
    try {
     // retrieve value for com.android.internal.R.id.title_container(=0x1020149)
     int titleContainerId = (Integer) Class.forName(
      "com.android.internal.R$id").getField("title_container").get(null);

     // remove all views from titleContainer
     ((ViewGroup) getWindow().findViewById(titleContainerId)).removeAllViews();

     // add new custom title view 
     getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, value);

    } catch(Exception ex) {
     // whatever you want to do here..
    }
}

I'm not sure whether the current setFeatureInt behaviour is intended, but it is certainly not documented one way or the other which is why I'll take this to the android devs ;)

EDIT

As pointed out in the comments, the aforementioned workaround is not ideal. Instead of relying on the com.android.internal.R.id.title_container constant you could simply hide the old custom title whenever you set a new one.

Let's assume you have two custom title layouts:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_1" ...

and

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/custom_title_2" ...

and you want to replace custom_title_1 with custom_title_2, you could hide former and use setFeatureInt to add the latter:

findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);
Josef
What if any of these values (title_container, com.android.internal) in the later versions? Won't that affect the app?
lostInTransit
You're absolutely right. Even though the com.android.internal.title_container constant is unlikely to change it is wrong to rely on it. This is an ugly workaround at best.
Josef
Thanks. This other solution works great. But I really don't understand why setFeatureInt should add views one above the other instead of replacing them? Esp with views which are bound to be singular - like the title!
lostInTransit
Are you still able to put a progress bar in the title bar when you do this? If so -- what ID would you give the progress bar in the title.
hwrdprkns
@hwrdprkns of course, just make the progress bar part of the `<RelativeLayout/>` described above
Josef
A: 

Just my 2c worth:

When working in a MapActivity, requesting a custom title resulted in no title at all being shown.

Luckily, all I wanted to do was to set the title text differently, and I soon realized that just calling setTitle() inside of onCreate() worked for me (I called it after I called setContentView())

Sorry, but I don't have time right now to debug this any more and figure out why what I was doing didn't work, and why changing it made it work. As I said, just thought this might help someone out down the road.

Hamy