Android: зачем setVisibility (View.GONE); или setVisibility (View.INVISIBLE); не работай

Я хочу, чтобы мой DatePicker и кнопка были невидимы вначале. И когда я нажимаю волшебную кнопку, я хочу установить видимость (View.Visible);

Проблема здесь в том, что я setVisibility(View.GONE) или setVisibility(View.INVISIBLE) ничего не меняю, а компонент все еще виден.

final DatePicker dp2 = (DatePicker) findViewById(R.id.datePick2);
final Button btn2 = (Button) findViewById(R.id.btnDate2);

dp2.setVisibility(View.GONE);
dp2.setVisibility(View.INVISIBLE);
btn2.setVisibility(View.GONE);
btn2.setVisibility(View.INVISIBLE);

btn2.setOnClickListener(new View.OnClickListener() {
    public void onClick(View arg0) {
        TextView txt2 = (TextView) findViewById(R.id.txt2);
        txt2.setText("You selected " + dp2.getDayOfMonth()
            + "/" + (dp2.getMonth() + 1) + "/" + dp2.getYear());
    }
});

person nayden    schedule 08.09.2011    source источник


Ответы (11)


Я вижу довольно много неправильных вещей. Во-первых, у вас не определена волшебная кнопка и нет для нее обработчика событий.

Также нельзя использовать:

dp2.setVisibility(View.GONE);
dp2.setVisibility(View.INVISIBLE); 

Используйте только один из двух. Из документации Android:

View.GONE Этот вид невидим и не занимает места для разметки.

View.INVISIBLE Это представление невидимо, но все же занимает место для разметки.

В вашем примере вы заменяете присвоение View.GONE назначением View.INVISIBLE.


Попробуйте заменить:

final DatePicker dp2 = new DatePicker(this)

с участием:

DatePicker dp2 = (DatePicker) findViewById(R.id.datePick2);  

Аналогично для других виджетов:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.VERTICAL);

        final DatePicker dp2 = new DatePicker(this);
        final Button btn2 = new Button(this);
        final Button magicButton = new Button(this);
        final TextView txt2 = new TextView(TestActivity.this);

        dp2.setVisibility(View.GONE);
        btn2.setVisibility(View.GONE);
        btn2.setText("set Date");

        btn2.setOnClickListener(new View.OnClickListener() {
            public void onClick(View arg0) {
                txt2.setText("You selected "
                    + dp2.getDayOfMonth() + "/" + (dp2.getMonth() + 1) 
                    + "/" + dp2.getYear());
            }
        });

        magicButton.setText("Magic Button");
        magicButton.setOnClickListener(new View.OnClickListener()    
            public void onClick(View arg0) {
                dp2.setVisibility(View.VISIBLE);
                btn2.setVisibility(View.VISIBLE);
            }
        });

    ll.addView(dp2);
    ll.addView(btn2);
    ll.addView(magicButton);
    ll.addView(txt2);

    setContentView(ll);
}
person con_9    schedule 08.09.2011
comment
API сообщает, что GONE: это представление невидимо и не занимает места для разметки. И НЕВИДИМЫЙ: этот вид невидим, но он все еще занимает место для разметки. Используйте тот, который соответствует вашим потребностям. - person gorlok; 26.07.2012

Вы можете думать об этом как о видимости и отображении в стиле CSS.

<div style="visibility:visible; display:block">
    This is View.VISIBLE : Content is displayed normally.
</div>

<div style="visibility:hidden; display:block">
    This is View.INVISIBLE : Content is not displayed, but div still takes up place, but empty.
</div>

<div style="display:none">
    This is View.GONE : Container div is not shown, you can say the content is not displayed.
</div>
person az3    schedule 04.03.2013

Сегодня у меня был сценарий, по которому я выполнял следующее:

myViewGroup.setVisibility(View.GONE);

Прямо в следующем кадре я выполнял if проверку состояния видимости этого вида где-то еще. Угадай, что? Выполнялось следующее условие:

if(myViewGroup.getVisibility() == View.VISIBLE) {
    // this `if` was fulfilled magically
}

Помещая точки останова, вы можете видеть, что видимость меняется на GONE, но прямо в следующем кадре она волшебным образом становится VISIBLE. Я пытался понять, как, черт возьми, это могло случиться.

Оказалось, что к этому представлению была применена анимация, которая внутренне заставила представление изменить его видимость на VISIBLE до завершения анимации:

public void someFunction() {
    ...
    TransitionManager.beginDelayedTransition(myViewGroup);
    ...

    myViewGroup.setVisibility(View.GONE);
}

Если вы отлаживаете, вы увидите, что myViewGroup действительно меняет свою видимость на GONE, но прямо в следующем кадре он снова станет видимым, чтобы запустить анимацию.

Итак, если вы столкнетесь с такой ситуацией, убедитесь, что вы не выполняете if проверку во время анимации представления.

Вы можете удалить всю анимацию в представлении с помощью View.clearAnimation() .

person azizbekian    schedule 03.01.2017
comment
Это ответ для меня (View.clearAnimation ()). Всегда вызывайте View.clearAnimation () в представлении, которое вы хотите установить в GONE, если вы знаете, что устанавливаете для него анимацию. - person Maxime Claude; 24.05.2017
comment
это действительно так, отладка не пролила никакого света, так как видимость действительно была настроена так, как ожидалось! - person Rainmaker; 22.01.2019
comment
Спасибо! Я потратил много времени, выясняя, почему не работает видимость, и ваше решение сработало для меня! - person rHd; 19.01.2021

Сначала посмотрите свой код:

dp2.setVisibility(View.GONE);
dp2.setVisibility(View.INVISIBLE);
btn2.setVisibility(View.GONE);
btn2.setVisibility(View.INVISIBLE);

Здесь вы устанавливаете видимость для одного и того же поля, вот в чем проблема. Я даю один образец для этой демонстрационного примера

person Parag Chauhan    schedule 08.09.2011
comment
ArrayAdapter ‹String› adapter7 = новый ArrayAdapter ‹String› (Application.getContext (), android.R.layout.simple_spinner_item, options ()); Spinner spinnerEnd = (Spinner) findViewById (R.id.spinnerEnd); адаптер7.setDropDownViewResource (android.R.layout.simple_spinner_dropdown_item); spinnerEnd.setAdapter (adapter7); spinnerEnd.setOnItemSelectedListener (новый AdapterView.OnItemSelectedListener () {public void onItemSelected (AdapterView ‹?› adapterView, View view, int i, long l) {dp2.setVisibility (View.VISIBLE); btn2.setVisibility (View.VISIBLE); - person nayden; 08.09.2011
comment
проблема отсюда. Зайдите внутрь onItemSelect - person nayden; 08.09.2011
comment
Попробуйте эту кнопку btn1, btn2; Спиннер спин; btn1 = (Кнопка) findViewById (R.id.button1); spin = (Spinner) findViewById (R.id.spinner1); String [] sample11 = {Sample, HI}; spin = (Spinner) findViewById (R.id.spinner1); ArrayAdapter ‹String› adapter = new ArrayAdapter ‹String› (this, android.R.layout.simple_spinner_item, sample11); spin.setAdapter (адаптер); btn1.setOnClickListener (new OnClickListener () {@Override public void onClick (View v) {// TODO Заглушка автоматически сгенерированного метода spin.setVisibility (View.GONE);}}); - person Parag Chauhan; 09.09.2011

В моем случае я обнаружил, что простая очистка анимации в представлении перед установкой видимости на GONE работает.

dp2.clearAnimation();
dp2.setVisibility(View.GONE);

У меня была аналогичная проблема, когда я переключаюсь между двумя представлениями, одно из которых всегда должно начинаться как GONE. Но когда я снова отображал представления, он отображался поверх первого представления, даже если был вызван setVisibility(GONE). Очистка анимации перед установкой просмотра на GONE сработала.

person Pierre    schedule 29.08.2019

View.GONE Этот вид невидим и не занимает места для разметки.

View.INVISIBLE Это представление невидимо, но все же занимает место для разметки.

dp2.setVisibility(View.GONE);
dp2.setVisibility(View.INVISIBLE);
btn2.setVisibility(View.GONE);
btn2.setVisibility(View.INVISIBLE);
person Pankaj Talaviya    schedule 30.08.2016

Это для тех, кто попробовал все ответы и все равно потерпел неудачу. Расширение ответа Пьера. Если вы используете анимацию, настройка видимости на GONE, INVISIBLE или invalidate() никогда не сработает. Попробуйте следующее решение. `

btn2.getAnimation().setAnimationListener(new Animation.AnimationListener() {
     @Override
     public void onAnimationStart(Animation animation) {
     }
     @Override
     public void onAnimationEnd(Animation animation) {
         btn2.setVisibility(View.GONE);
         btn2.clearAnimation();
     }
     @Override
     public void onAnimationRepeat(Animation animation) {
     }
});

`

person karthik vishnu kumar    schedule 24.11.2019

View.GONE делает вид невидимым, не занимая места в макете. View.INVISIBLE делает вид просто невидимым, по-прежнему занимая место.

Сначала вы используете GONE, а затем INVISIBLE в том же представлении. Поскольку код выполняется последовательно, сначала представление становится GONE, затем оно заменяется типом INVISIBLE, все еще занимающим место.

Вы должны добавить прослушиватель кнопки на кнопку и внутри метода onClick () сделать представления видимыми. По моему мнению, это должна быть логика вашего метода onCreate ().

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_setting);

    final DatePicker dp2 = (DatePicker) findViewById(R.id.datePick2);
    final Button btn2 = (Button) findViewById(R.id.btnDate2);
    final Button btn3 = (Button) findViewById(R.id.btnVisibility);

    dp2.setVisibility(View.INVISIBLE);
    btn2.setVisibility(View.INVISIBLE);

    bt3.setOnClickListener(new View.OnCLickListener(){ 
    @Override
    public void onClick(View view)
    {
        dp2.setVisibility(View.VISIBLE);
        bt2.setVisibility(View.VISIBLE);
    }
  });
}

Я думаю, это должно сработать легко. Надеюсь это поможет.

person Trishant Sharma    schedule 28.02.2018

Я также столкнулся с той же проблемой: если предположить, что этот конкретный фрагмент раздувается на разных экранах, есть вероятность, что режимы видимости, установленные внутри операторов if, не будут работать в соответствии с нашими потребностями, поскольку условие могло быть сброшено, когда оно было раздуто. несколько раз в нашем приложении.

В моем случае мне нужно изменить режим видимости в одном фрагменте (дочернем фрагменте) на основе нажатия кнопки в другом фрагменте (родительский фрагмент). Поэтому я сохранил логическое значение buttonClicked в переменной родительского фрагмента и передал его как параметр функции в дочернем фрагменте. Таким образом, режимы видимости в дочерних фрагментах изменяются на основе этого логического значения, полученного через параметр. Но поскольку этот дочерний фрагмент раздувается на разных экранах, режимы видимости продолжают сбрасываться, даже если я скрою его с помощью View.GONE.

Чтобы избежать этого конфликта, я объявил статическую логическую переменную в дочернем фрагменте, и всякий раз, когда это логическое значение получено из родительского фрагмента, я сохранял его в статической переменной, а затем менял режимы видимости на основе этой статической переменной в дочернем фрагменте .

Это решило проблему для меня.

person Sai Teja    schedule 21.10.2020

Однажды у меня была такая же проблема. Вызов недействительности после изменения видимости почти всегда работает, но в некоторых случаях - нет. Мне пришлось схитрить и установить для фона прозрачное изображение, а для текста -.

person tanaijing    schedule 13.11.2020

Потому что вы устанавливаете видимость либо true, либо false. попробуйте, чтобы setVisible(0) стал видимым истинным. and setVisible(4) в видимую ложь.

person ali    schedule 08.09.2011
comment
текст может быть невидимым, но кнопки и датпикера нет. - person nayden; 08.09.2011
comment
НЕ ИСПОЛЬЗУЙТЕ буквальные целые числа, это плохая привычка, используйте вместо этого View.GONE или View.VISIBLE ... - person Lukap; 08.09.2011