Android - 在运行时更改自定义标题视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/820398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android - change custom title view at run time
提问by lostInTransit
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.
我在我的应用程序中为每个活动使用自定义标题视图。在其中一项活动中,基于单击按钮,我需要更改自定义标题视图。现在每次我调用 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.
这是我尝试过的。即使调用 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();
回答by Josef Pfleger
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 replacedbut attachedto the internal title container and thus drawn on top of each other.
问题是,只有Window
实现(PhoneWindow
)使用LayoutInflater
其setFeatureInt
方法与实例化新的布局inflate
和attachToRoot=true
。因此,当您调用 时setFeatureInt
,新布局不会被替换,而是附加到内部标题容器,从而在彼此之上绘制。
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:
您可以通过使用以下辅助方法而不是setFeatureInt
. 在设置新的自定义标题功能之前,助手简单地从内部标题容器中删除所有视图:
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 ;)
我不确定当前的setFeatureInt
行为是否是有意的,但它肯定没有以一种或另一种方式记录在案,这就是为什么我将其带到 android 开发人员;)
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 hidethe old custom title whenever you set a new one.
正如评论中所指出的,上述解决方法并不理想。无需依赖com.android.internal.R.id.title_container
常量,您可以在设置新标题时简单地隐藏旧的自定义标题。
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:
并且您想替换custom_title_1
为custom_title_2
,您可以隐藏前者并使用setFeatureInt
添加后者:
findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);
回答by James Oltmans
The correct way to do this is as follows:
正确的方法如下:
requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );
Please note that the order of these statements is very important.
请注意,这些语句的顺序非常重要。
If you call super.onCreate() before any of the other statements you will get a blank title bar, which the hack of finding the title bar id and removing all the Views from it will fix but is not recommended.
如果您在任何其他语句之前调用 super.onCreate() ,您将得到一个空白的标题栏,找到标题栏 id 并从中删除所有视图的黑客将修复但不推荐。
回答by haseman
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?
更新文本后,您是否调用 invalidate 或 postInvalidate 来重绘视图?如果它是自定义视图,您能否在绘制代码中放置一个断点以确保它被调用?
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.
如果您在 UI 线程上,则可以调用 'invalidate' 如果不在,则必须调用 'postInvalidate' 否则视图不会重绘自身。
回答by Hamy
Just my 2c worth:
只是我的 2c 价值:
When working in a MapActivity, requesting a custom title resulted in no title at all being shown.
在 MapActivity 中工作时,请求自定义标题导致根本没有显示标题。
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())
幸运的是,我想做的就是以不同的方式设置标题文本,我很快意识到在 onCreate() 中调用 setTitle() 对我有用(我在调用 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.
对不起,但我现在没有时间再调试它并弄清楚为什么我所做的不起作用,以及为什么改变它使它起作用。正如我所说,只是认为这可能会帮助某些人。