Re: Светофор

alexander.klimoff wrote:

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

Верно, спасибо большое. Прежде чем задать вопрос, несколько раз просмотрел код, но не увидел явную ошибку:

                mInfoTextView.setText(R.string.green);
                mInfoTextView.setBackgroundColor(getResources().getColor(R.color.greenColor));

Re: Светофор

Здравствуйте, уважаемый Александр! Почему-то в вашем коде:

  public void onRedButtonClick(View view) {
        mInfoTextView.setText(R.string.red);
        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
    }

    public void onGreenButtonClick(View view) {
        mInfoTextView.setText(R.string.green);
        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.greenColor));

зелёный цвет работать отказывается.
А вот если я задаю в его в методе onCreate по аналогии с желтым, то всё прекрасно)
С чем это может быть связано?

Re: Светофор

Это связано исключительно с вашей невнимательностью. А код для красной кнопки работает? Если да, то задумайтесь - код абсолютно идентичен, просто подставляются другие цвета.

Re: Светофор

Отличные статьи, все предельно понятно написано. Реализовал все в одном методе:
    public void pressButton(View view) {
        switch(view.getId()){
            case R.id.buttonRed:
                mColorBackground.setBackgroundColor(ContextCompat.getColor(this, R.color.colorRed));
                mTextColor.setText(R.string.buttonRed);
                break;

            case R.id.buttonYellow:
                mColorBackground.setBackgroundColor(ContextCompat.getColor(this, R.color.colorYellow));
                mTextColor.setText(R.string.buttonYellow);
                break;

            case R.id.buttonGreen:
                mColorBackground.setBackgroundColor(ContextCompat.getColor(this, R.color.colorGreen));
                mTextColor.setText(R.string.buttonGreen);
                break;
        }
    }

Не знаю насколько целесообразно конкретно здесь, но все же, на будущее. Смущает многократный вызов setText/setBackgroundColor. Можно ли в case записать в переменные значения цвета/текста и после switch один раз прописать вызов setText/setBackgroundColor ?

Re: Светофор

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

Re: Светофор

c0gu wrote:

Здравствуйте, уважаемый Александр! Почему-то в вашем коде:

  public void onRedButtonClick(View view) {
        mInfoTextView.setText(R.string.red);
        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
    }

    public void onGreenButtonClick(View view) {
        mInfoTextView.setText(R.string.green);
        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.greenColor));

зелёный цвет работать отказывается.
А вот если я задаю в его в методе onCreate по аналогии с желтым, то всё прекрасно)
С чем это может быть связано?

Была аналогичная проблема. Вроде бы все правильно, но зеленый не реагирует.
Оказалось, что пропустила строку " android:onClick="onGreenButtonClick" в activity_main.xml

Re: Светофор

Error:(29, 75) error: incompatible types: <anonymous OnClickListener> cannot be converted to Context

Выдает ошибку в

public class MainActivity extends AppCompatActivity {

    private RelativeLayout mRelativeLayout;
    private TextView mInfoTextView;

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

        mRelativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
        mInfoTextView = (TextView) findViewById(R.id.textView);

        Button yellowButton = (Button) findViewById(R.id.buttonYellow);
        yellowButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mInfoTextView.setText(R.string.yellow);
                mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.yellowColor));
            }
        });
    }

все как в примере, только через this.
ничего не понимаю (((

Re: Светофор

this в вашем случае относится к области View, а у него нет доступа к контексту. Поэтому нельзя так писать. Нужно указать другой объект, который может работать с контекстом.

Re: Светофор

Александр, спасибо Вам за статьи.

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

Вопрос про устаревший метод getColor(int id).

Если я правильно понимаю должны существовать устройства которые поддерживают устаревший метод getColor(int id)
и если написать так: ContextCompat.getColor(this, R.color.yellowColor)
такие устройства выдадут ошибку (мое предположение), т.к. в старых версиях библиотеки совместимости нет этого метода.

Вопрос:

Как написать код так, что бы он работал без ошибок?

Возможно у меня бы не возник данный вопрос, но код: getResources().getColor(R.color.yellowColor, null)
у меня не работает?!

Тестирую все на планшете, Android 4.2.2

            case R.id.buttonRed:
                mTextView.setText(R.string.red);
                // Работает с помощью библиотеки совместимости
                mRelativeLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.colorRed));
                break;
            case R.id.buttonYellow:
                mTextView.setText(R.string.yellow);
                // Не рабротает
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.colorYellow, null));
                break;
            case R.id.buttonGreen:
                mTextView.setText(R.string.green);
                // Работает не смотря на то, что Android Studio зачеркнула getColor
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.colorGreen));
                break;

И еще вопрос, если метод устарел значит нужно от него отказываться, как правильно написать код не используя устаревший метод?

Re: Светофор

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

Вот все варианты на примере закрашивания кнопки
        Button redButton = (Button) findViewById(R.id.buttonRed);
        redButton.setBackgroundColor(getResources().getColor(R.color.redColor));
        redButton.setBackgroundColor(getResources().getColor(R.color.redColor, null));
        redButton.setBackgroundColor(ContextCompat.getColor(this, R.color.redColor));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            redButton.setBackgroundColor(this.getResources().getColor(android.R.color.white, this.getTheme()));
        }else {
            redButton.setBackgroundColor(this.getResources().getColor(android.R.color.white));
        }

Первый метод устарел, но можно использовать.
Второй метод использует новый способ. Должен работать при установке необходимых версий SDK.
Третий метод также использует новый способ из библиотеки совместимости последних версий.
Последний вариант с условием, чтобы код использовал нужный метод в Android 6, а в старых версиях старый метод.

Все способы должны работать. Если у вас не работает ваш способ, то возможно вы не установили нужный SDK или не указали в проекте последнюю версию для разработки.

Re: Светофор

Спасибо. Получилось. У кого вылетает приложение с 1000 ошибок при нажатии на любую кнопку в эмуляторе, Вы просто не присвоили id relativeLayout. Я ты тыкал мыкал, переписывал пару раз. А потом пробежал глазами по уроку. и тут опа.

Re: Светофор

День добрый Александр! Проблема с ДЗ. Со значками все получилось и программа работала как надо, но вот при попытке все вписать в один обработчик в эмуляторе вылетает краш:

04-06 16:49:27.444 7223-7223/ru.devotion.dev006 E/AndroidRuntime: FATAL EXCEPTION: main
                                                                  Process: ru.devotion.dev006, PID: 7223
                                                                  java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{ru.devotion.dev006/ru.devotion.dev006.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2236)
                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
и так далее красным цветом.

Код .java:


package ru.devotion.dev006;

import ...


public class MainActivity extends AppCompatActivity implements OnClickListener{
    private TextView mInfoTextView;
    private Button buttonRed = (Button)findViewById(R.id.buttonRed);
    private Button buttonYellow = (Button)findViewById(R.id.buttonYellow);
    private Button buttonGreen = (Button)findViewById(R.id.buttonGreen);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mInfoTextView = (TextView)findViewById(R.id.textView);
        buttonRed.setOnClickListener(this);
        buttonYellow.setOnClickListener(this);
        buttonGreen.setOnClickListener(this);
    }


}
Пытался понять, о чем говорит андройд монитор, но в силу малого опыта не могу понять, на что ругается. (Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference)

Подскажите, где котяра в сметану залез и не признается? sad

З.Ы. (я временно убрал изменение фона по клику на кнопки, ибо даже изменение текста не происходит)

Re: Светофор

Инициализация компонентов должна происходить в методах. Посмотрите на TextView, который объявлен правильно.

39 (edited by DevotioN 2016-04-18 17:44:24)

Re: Светофор

Спасибо Александр! все получилось! А можете рассказать, на что жалуется (не критично) студия в этой строке:

private Button buttonRed;
(выводится вот такой месседж-подсказка)

Field can be converted to a local variable less... (Ctrl+F1)
This inspection searches for redundant class fields that can be replaced with local variables. If all local usages of a field are preceded by assignments to that field, the field can be removed and its usages replaced with local variables.



В детстве любил программировать на бейсике 48 и осталась привычка узнавать досканально и синтаксис и оптимизацию=) Спасибо)


_________________________________________________________________

Добавлю: я примерно понял что требовала студия. При нажатии ALT+ENTER он предложил перевести переменную в "локальную" (???)

После чего код выглядел так:

public class MainActivity extends AppCompatActivity implements OnClickListener{
    private TextView mInfoTextView;
    private RelativeLayout mRelativeLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mInfoTextView = (TextView)findViewById(R.id.textView);
        Button buttonRed = (Button) findViewById(R.id.buttonRed);
        Button buttonYellow = (Button) findViewById(R.id.buttonYellow);
        Button buttonGreen = (Button) findViewById(R.id.buttonGreen);
        mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
        buttonRed.setOnClickListener(this);
        buttonYellow.setOnClickListener(this);
        buttonGreen.setOnClickListener(this);
    }
     далее стандартно.

Программа работала, но теперь студия ругалась на:
        buttonRed.setOnClickListener(this);
        buttonYellow.setOnClickListener(this);
        buttonGreen.setOnClickListener(this);

При том же нажатии на ALT+ENTER студия добавила перед каждой из этих строчек выражение:

        assert buttonYellow != null;

Можете пояснить зачем и что это значит? Обычно null это пустой или дефолтный. Но я так и не понял это выражение.

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

package ru.devotion.dev006;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.RelativeLayout;
import android.view.View.OnClickListener;


public class MainActivity extends AppCompatActivity implements OnClickListener{
    private TextView mInfoTextView;
    private RelativeLayout mRelativeLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mInfoTextView = (TextView)findViewById(R.id.textView);
        Button buttonRed = (Button) findViewById(R.id.buttonRed);
        Button buttonYellow = (Button) findViewById(R.id.buttonYellow);
        Button buttonGreen = (Button) findViewById(R.id.buttonGreen);
        mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
        assert buttonRed != null;
        buttonRed.setOnClickListener(this);
        assert buttonYellow != null;
        buttonYellow.setOnClickListener(this);
        assert buttonGreen != null;
        buttonGreen.setOnClickListener(this);
    }
    @Override
    public void onClick(View v){
        switch (v.getId()) {
            case R.id.buttonRed: mInfoTextView.setText(R.string.red);
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
                break;
            case R.id.buttonYellow: mInfoTextView.setText(R.string.yellow);
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.yellowColor));
                break;
            case R.id.buttonGreen: mInfoTextView.setText(R.string.green);
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.greenColor));
                break;
        }
    }
}


//package ru.devotion.dev006;

//        import android.support.v7.app.AppCompatActivity;
//        import android.os.Bundle;
//        import android.view.View;
//        import android.widget.RelativeLayout;
//        import android.widget.TextView;

//public class MainActivity extends AppCompatActivity {
//    private RelativeLayout mRelativeLayout;
//    private TextView mInfoTextView;

//    @Override
//    protected void onCreate(Bundle savedInstanceState) {
//        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
//        mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
//        mInfoTextView = (TextView)findViewById(R.id.textView);
//    }

//    public void onRedButtonClick(View view) {
//        mInfoTextView.setText(R.string.red);
//        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.redColor));
//    }
//    public void onYellowButtonClick(View view) {
//        mInfoTextView.setText(R.string.yellow);
//        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.yellowColor));
//    }
//    public void onGreenButtonClick(View view) {
//        mInfoTextView.setText(R.string.green);
//        mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.greenColor));
//    }
//}

Re: Светофор

Студия говорит, что переменную можно сделать локальной, так как она нигде не используется, кроме как в одном методе. Если подвести мышку к этой строке, дождаться всплывающего значка и щелкнуть по нему, то это произойдет автоматически. Или вручную можно перенести в onCreate()

41 (edited by DevotioN 2016-04-18 17:48:44)

Re: Светофор

Спасибо) я так и подумал про локальную переменную) а можете тогда рассказать, зачем потом требовались строчки

assert button***** != null;

(пока я редактировал пост выше, вы ответили про локальную))

Re: Светофор

С assert в студии на мой взгляд погорячились. Даже в примерах от Гугла я его не встречал. Поэтому не обращайте внимание на эту помощь и не пользуйтесь им. Ваш вариант выше является рабочим, оставляйте и спите спокойно.

43 (edited by Nik 2017-01-07 19:59:26)

Re: Светофор

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

Re: Светофор

Есть урок, как передавать данные во вторую активность. Цвет - это число. Передать число и поменять цвет.

45

Re: Светофор

День добрый, Александр. Прежде всего хотел бы выразить большую благодарность за проделанную работу над уроками. Действительно все понятно и доступно smile

Возникла проблема. Не выходит реализовать светофор через одну функцию. Студия ошибок не выдает, однако когда запускаю на эмуляторе (использую сторонний YouWave), выдает ошибку   "Unfortunately, ProjectName has stopped".
Помогите пожалуйста разобраться.

P.S Очень люблю котиков smile

   package com.example.netbook.train;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.view.View.OnClickListener;

import static com.example.netbook.train.R.layout.activity_main;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    final Button butRed = (Button) findViewById(R.id.butRed);
    final Button butYellow = (Button) findViewById(R.id.butYellow);
    final Button butGreen = (Button) findViewById(R.id.butGreen);

    private RelativeLayout mRelativeLayout;
    private TextView mColorInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(activity_main);
        mRelativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
        mColorInfo = (TextView) findViewById(R.id.InfoColor);
        butRed.setOnClickListener(this);
        butYellow.setOnClickListener(this);
        butGreen.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.butRed:
                mColorInfo.setText(R.string.red);
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.colorRed));
                break;

            case R.id.butYellow:
                mColorInfo.setText(R.string.yellow);
                mRelativeLayout.setBackgroundColor(getResources().getColor(R.color.colorYellow));
                break;

        }
    }


}

Re: Светофор

Пройдите еще раз урок Hello Kitty и сами поймете,  в чем ошибка

Re: Светофор

Добрый день, Александр. Спасибо за уроки, за хорошо изложеный материал и котиков)
Никак не могу осилить "Светофор" - приложение компилится без ошибок, но на эмуляторе не запускается (предлагает сначала перезапустить, потом закрыть). При этом, если закомментарить строку
  mRelativeLayout = (RelativeLayout)findViewById(R.id.relativeLayout);
и все последующие обращения к mRelativeLayout, то работает исправно... Id для layout'а прописал, relativeLayout. Пробовал через редактор свойств указать relativeLayout, пробовал в XML'ке @+id/relativeLayout - ни один вариант не сработал. Что я делаю не так?
Студия v2.3, SDK v25, эмулятор на Android 7.1.

Re: Светофор

Что-то упустили. Лучше, если пришлете письмо и скопируете код разметки и активности.

Re: Светофор

alexander.klimoff wrote:

Что-то упустили. Лучше, если пришлете письмо и скопируете код разметки и активности.

А, нашел, в чем дело. У Вас по умолчанию в дефолтном проекте используется контейнер RelativeLayout? У меня ConstraintLayout... Соответственно, при попытке привести его к типу relativeLayout приложение и валилось. Проект пробовал создавать и с обратной совместимостью, и без, и с разными MinSDK - все равно у меня подставляет ConstraintLayout. Ладно, буду иметь в виду. Спасибо за обратную связь)

Re: Светофор

Все-таки странная у вас логика. В статье приводится код разметки. Вы используете свою разметку, приложение падает. Вы считаете, что все делали по уроку и не понимаете причину.