setVisibility(View.VISIBLE)并不总是有效。有什么想法吗?

23

我试图展示一对隐藏的按钮(使用setVisibility(View.VISIBLE),在RelativeLayout中),但它并不总是有效。该按钮在Galaxy Tab 10.1"上显示正常,但在较小的平板电脑(不确定型号)和Android 4.0模拟器上则不行。

我偶然发现,对于某个TextView t,以下代码会使按钮可见:

t.setText(t.getText());
...
button.setVisibility(View.VISIBLE);

t位于同一个RelativeLayout中,但与按钮无关(它们的位置是独立且不重叠的)。

编辑:如果有Android开发人员想要追踪此问题...

我能够将代码简化为以下布局,在Android 4.0.3模拟器上展示了该问题,但在Galaxy Tab上没有。我发现我需要一个SurfaceView,否则问题就不会出现(例如,将其更改为TextView,问题就消失了)。

<?xml version="1.0" encoding="utf-8"?>
<!-- layout/test.xml -->
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"        
    android:id="@+id/relativeLayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <SurfaceView
        android:id="@+id/mapCtrl"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/bottomPanel"
        android:text="Placeholder"
        android:layout_marginTop="18dip" />
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="@string/map_mode_title" />

    <!--=================================================-->
    <!-- Bottom bar: current road name and current speed -->
    <LinearLayout
        android:id="@+id/bottomPanel"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#f228"
        android:orientation="horizontal"
        android:textColor="#ffff" >
        <Button
            android:id="@+id/btnNavMode"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_marginRight="3dip"
            android:textColor="#fff"
            android:text="Switch to\nNav Mode" />
        <RelativeLayout
            android:id="@+id/currentStreetPanel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:clickable="true"
            android:orientation="vertical" >
            <TextView
                android:id="@+id/currentStreetHdg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:text="Current street"
                android:textColor="#fff"
                android:textSize="10dip" />
            <TextView
                android:id="@+id/currentStreet"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/currentStreetHdg"
                android:layout_marginTop="-8dip"
                android:singleLine="true"
                android:text="Current street"
                android:textColor="#fff"
                android:textSize="30dip" />
        </RelativeLayout>
        <RelativeLayout
            android:id="@+id/RelativeLayout2"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="#ff606060"
            android:orientation="vertical" >
            <TextView
                android:id="@+id/yourSpeedHdg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:layout_marginLeft="3dip"
                android:text="Your speed"
                android:textColor="#fff"
                android:textSize="10dip" />
            <TextView
                android:id="@+id/speed"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/yourSpeedHdg"
                android:layout_marginLeft="3dip"
                android:layout_marginTop="-8dip"
                android:text="0"
                android:textColor="#fff"
                android:textSize="30dip" />
            <TextView
                android:id="@+id/speedUnit"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBaseline="@+id/speed"
                android:layout_marginLeft="5dip"
                android:layout_toRightOf="@+id/speed"
                android:text="kph"
                android:textColor="#fff"
                android:textSize="18dip" />
        </RelativeLayout>
    </LinearLayout>

    <!--================-->
    <!-- On-map buttons -->
    <Button
        android:id="@+id/btnClearRoute"
        android:background="#F00"
        android:textColor="#fff"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Clear\nroute"/>
    <ZoomControls
        android:id="@+id/zoomControls"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/mapCtrl"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="-25dip"
        android:orientation="horizontal" />
    <Button
        android:id="@+id/btnFindRoute"
        android:layout_width="100dip"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/mapCtrl"
        android:layout_alignParentRight="true"
        android:layout_marginRight="2dip"
        android:layout_marginBottom="65dip"
        android:text="Route to selected location"
        android:textSize="17dip"/>
    <Button
        android:id="@+id/btnUnselect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/btnFindRoute"
        android:layout_alignTop="@+id/btnFindRoute"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="2dip"
        android:text="Unselect" />
    <LinearLayout
        android:id="@+id/showMePanel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/btnFindRoute"
        android:layout_alignRight="@+id/btnFindRoute"
        android:layout_alignLeft="@+id/btnFindRoute"
        android:padding="4dip"
        android:background="#bbbb"
        android:gravity="center"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Show me..."
            android:textColor="#fff"/>
        <Button
            android:id="@+id/btnShowVehicle"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="My car"/>
        <Button
            android:id="@+id/btnShowRoute"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="The route"/>
        <Button
            android:id="@+id/btnShowDestination"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Destination"/>
        <Button
            android:id="@+id/btnShowMap"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="The map"/>
    </LinearLayout>
</RelativeLayout>

当任意一个按钮被点击时,Activity类会简单地切换两个按钮的可见性。在某些设备上,它可以正常工作,而在其他设备上则无法正常工作。

package mentor.simplegps;

import android.app.*;
import android.os.Bundle;
import android.view.*;
import android.widget.*;

public class TestActivity extends Activity implements View.OnClickListener
{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.test);
        boilerplate();
        setVisibilities();
    }

    Button _btnShowMap, _btnShowVehicle, _btnShowRoute, _btnShowDestination;
    Button _btnUnselect, _btnFindRoute, _btnNavMode;
    TextView _title;

    void boilerplate()
    {
        _btnUnselect = attachBtn(R.id.btnUnselect);
        _btnShowMap = attachBtn(R.id.btnShowMap);
        _btnShowVehicle = attachBtn(R.id.btnShowVehicle);
        _btnShowRoute = attachBtn(R.id.btnShowRoute);
        _btnShowDestination = attachBtn(R.id.btnShowDestination);
        _btnFindRoute = attachBtn(R.id.btnFindRoute);
        _btnNavMode = attachBtn(R.id.btnNavMode);
        _title = (TextView)findViewById(R.id.title);
    }
    private Button attachBtn(int btnId) {
        Button b = (Button)findViewById(btnId);
        b.setOnClickListener(this);
        return b;
    }

    boolean haveSel;
    public void onClick(View v)
    {
        haveSel = !haveSel;
        setVisibilities();
    }
    void setVisibilities()
    {
        _btnFindRoute.setVisibility(haveSel ? View.VISIBLE : View.INVISIBLE);
        _btnUnselect.setVisibility (haveSel ? View.VISIBLE : View.INVISIBLE);

        // Fixes the problem
        //_title.setText(_title.getText());
    }
}
5个回答

46

SurfaceView是罪魁祸首(当然,GLSurfaceView、RSSurfaceView和VideoView都继承自SurfaceView,也同样适用)。在处理其上的其他视图时,它会展现出许多奇怪的行为。使用View.setVisibility()时就是其中之一。显然,SurfaceView并没有被设计成与其他视图一起使用(尽管官方文档中说应该这样做),而是作为视频、游戏或OpenGL图形的独立视图。

对于可见性问题,我发现使用View.GONE而不是View.INVISIBLE可以解决这个问题。如果您不想使用GONE,例如,可以尝试更改焦点(并返回到之前具有焦点的位置),或更改其他状态。目的是以某种方式唤醒底层UI系统。

简而言之:如果在您的视图中发生了奇怪的事情,并且您的某个地方有SurfaceView(或其子类),请尝试将其替换为其他内容,以便您在做正确的事情时不会浪费时间搜索出错原因(并且没有错误的信念)。这样,您就知道SurfaceView是罪魁祸首,可以用美丽的评论来绕过它,毫不犹豫地抨击它。


1
我有过类似的情况,但没有涉及SurfaceView。试图在INVISIBLE和VISIBLE之间切换没有起作用。但是从GONE到VISIBLE却有效了。谁知道呢。 - Peri Hartman
我尝试在与match parent大小重叠的视图上使用GONE/VISIBLE,但它没有起作用,最终不得不使SurfaceView GONE。 - Prakash
不幸的是,如果SurfaceView被用作相机预览输出,将其可见性更改为“GONE”将导致表面被销毁。如果surfaceDestroyed与相机最终化代码挂钩(当两者一起使用时会出现这种情况),则需要更多的代码来解决这个问题。 - rwong
经过8个小时的努力,我在这里停下了。好的解决方案。谢谢 :) - Daxesh Vekariya

21

记录一下:我碰到了这个问题,尝试了很多随机的东西(谢谢Alex!),在我的情况下,解决它的方法是在那个拒绝显示的拖动条上直接执行seekBar.requestLayout(),紧跟setVisible。


太好了! :) 这对我有用。我在相机中隐藏了一个按钮,当我需要显示它时,将其设置为可见并请求布局。 - Juan Munhoes Junior

5

这是我的解决方案。

setAlpha(0)
btnName.setAlpha(0)

可以在所有视图中正常工作,例如按钮、图片、文本等。


0

我(非常烦人地)遇到了类似的问题,即在SurfaceView预览上放置一个按钮,并且不得不将按钮放在RelativeLayout中,并使RelativeLayout可见/不可见。对于其他遇到相同问题的人来说,这可能值得一试。

...而且我还必须在findViewById之后编程调用布局:buttonLayout.bringToFront()。


0
在我的情况下,View.VISIBLE/View.GONE 并不总是起作用。当我将开关切换到 View.VISIBLE/View.INVISIBLE 时,它开始按预期工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接