Android - 在运行时更改自定义标题视图

Posted

技术标签:

【中文标题】Android - 在运行时更改自定义标题视图【英文标题】:Android - change custom title view at run time 【发布时间】:2010-10-23 15:40:38 【问题描述】:

我在我的应用程序中为每个活动使用自定义标题视图。在其中一项活动中,基于按钮单击,我需要更改自定义标题视图。现在每次我调用 setFeatureInt 时都可以正常工作。

但是,如果我尝试更新自定义标题中的任何项目(例如更改按钮的文本或标题上的文本视图),则不会进行更新。

通过代码调试显示文本视图和按钮实例不为空,我还可以看到自定义标题栏。但是文本视图或按钮上的文本没有更新。有没有其他人遇到过这个问题? 我该如何解决?

谢谢。

编辑

这是我尝试过的。即使调用 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();

【问题讨论】:

看到这个替代解决方案***.com/questions/8634319/… 【参考方案1】:

问题是唯一的Window 实现(PhoneWindow)在其setFeatureInt 方法中使用LayoutInflater,并使用inflateattachToRoot=true 实例化新布局。因此,当您调用setFeatureInt 时,新布局不会替换,而是附加到内部标题容器,从而相互叠加。

您可以通过使用以下辅助方法而不是 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..
    

我不确定当前的 setFeatureInt 行为是否是有意的,但它肯定没有以一种或另一种方式记录,这就是为什么我将把它带到 android 开发者那里;)

编辑

正如 cmets 中所指出的,上述解决方法并不理想。您可以在设置新标题时隐藏旧的自定义标题,而不是依赖com.android.internal.R.id.title_container 常量。

假设您有两个自定义标题布局:

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

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

如果您想将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);

【讨论】:

如果这些值(title_container、com.android.internal)中的任何一个在更高版本中出现怎么办?这不会影响应用吗? 你说得对。尽管 com.android.internal.title_container 常量不太可能改变,但依赖它是错误的。这充其量是一个丑陋的解决方法。 谢谢。这个其他解决方案效果很好。但我真的不明白为什么 setFeatureInt 应该在另一个之上添加视图而不是替换它们?尤其是带有一定是单数的视图 - 就像标题一样! 当你这样做时,你还能在标题栏中放一个进度条吗?如果是这样 - 你会给标题中的进度条提供什么 ID。 @hwrdprkns 当然,只需将进度条作为上述&lt;RelativeLayout/&gt; 的一部分【参考方案2】:

正确的做法如下:

requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );

请注意,这些语句的顺序非常重要。

如果您在任何其他语句之前调用 super.onCreate(),您将获得一个空白标题栏,查找标题栏 ID 并从中删除所有视图的黑客将修复此问题,但不建议这样做。

【讨论】:

OP 试图在运行时更改标题栏,在 onCreate() 之后。【参考方案3】:

你是在更新文本后调用 invalidate 还是 postInvalidate 来重绘视图?如果是自定义视图,能否在绘制代码中设置断点以确保它被调用?

如果你在 UI 线程上,你可以调用'invalidate',如果你不在,你必须调用'postInvalidate',否则视图不会重绘自己。

【讨论】:

如果有帮助,将重绘视图,因为我看到更新的标题栏,但标题栏上的控件没有改变【参考方案4】:

只是我的 2c 价值:

在 MapActivity 中工作时,请求自定义标题会导致根本不显示任何标题。

幸运的是,我想做的只是设置不同的标题文本,我很快意识到在 onCreate() 中调用 setTitle() 对我有用(我在调用 setContentView() 后调用了它)

抱歉,但我现在没有时间再调试它并弄清楚为什么我正在做的事情不起作用,以及为什么改变它使它起作用。正如我所说,只是认为这可能会帮助别人。

【讨论】:

以上是关于Android - 在运行时更改自定义标题视图的主要内容,如果未能解决你的问题,请参考以下文章

检索自定义视图时的 Android ClassCastException

在 Android Studio 中向列表视图添加自定义行

如何处理自定义 android 视图/小部件的可见性更改

长按自定义项 UICollectionViewCell 图像更改

Xib 自定义 UIView 的实例化

Android recyclerview拖拽自定义功能