SetVisibility (View.VISIBLE) не всегда работает. Идеи?

Я пытаюсь показать пару скрытых кнопок (используя setVisibility(View.VISIBLE), внутри RelativeLayout), но это не всегда работает. Кнопка показывает OK на вкладке 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());
    }
}

Ответы

Ответ 1

SurfaceView является единственным виновником (конечно, это также относится к GLSurfaceView, RSSurfaceView и VideoView, все из которых наследуется от SurfaceView). Он раскрывает множество странных поведений, когда имеет дело с другими представлениями поверх него. Воспроизведение с View.setVisibility() является одной из этих проблем. Очевидно, что SurfaceView не был разработан для использования с другими представлениями (хотя официальный документ говорит, что это должно быть), но как отдельное представление для видео, игр или продуктов OpenGL.

В связи с проблемой видимости, я обнаружил, что с помощью View.GONE вместо View.INVISIBLE разрешите его. Если вы не хотите использовать GONE, попробуйте, например, сфокусировать фокус (и вернуться к тому, на котором раньше была фокус) или изменить другие состояния. Цель состоит в том, чтобы как-то разбудить базовую систему пользовательского интерфейса.

Вкратце: когда что-то странное происходит с вашими взглядами, и у вас есть SurfaceView (или подкласс) где-то, попробуйте заменить его чем-то другим, чтобы вы не теряли часы в поисках того, что вы делаете неправильно, когда вы это делаете право (и без ложных убеждений). Таким образом, вы знаете, что SurfaceView виноват, и вы можете взломать его красивыми комментариями, чтобы мочиться на нем без угрызений совести.

Ответ 2

Для записи: у меня была эта проблема, попробовал кучу случайных вещей (спасибо Alex!), и в моем случае то, что решило это, делало seekBar.requestLayout() непосредственно после setVisible на самом баре, который отказывался показывать.

Ответ 3

Это мое решение

setAlpha(0)
btnName.setAlpha(0)

Работает для всех видов, таких как = > Кнопки - Изображения - Тексты и...

Ответ 4

В моем случае View.VISIBLE/View.GONE не работал всегда. Когда я переключил переключатель на View.VISIBLE/View.INVISIBLE, он начал работать по назначению.

Ответ 5

I (досадно) испытывала схожие трудности с наличием кнопки поверх предварительного просмотра SurfaceView и должна была поместить кнопку в RelativeLayout и сделать RelativeLayout VISIBLE/INVISIBLE. Возможно, стоит того, чтобы кто-то еще имел ту же проблему.

... И мне также пришлось программно вызывать макет, который должен быть перенесен с: buttonLayout.bringToFront() сразу после findViewById.