Как динамически ссылаться на ресурсы в папке R. drawable в Android?

#java #android #android-studio

Вопрос:

У меня есть следующий код для моего адаптера:

 @Override
public void onBindViewHolder(GameViewHolder holder, int position) {
    final Games game = gameList.get(position);
    holder.awayTeamImageView.setBackgroundResource(R.drawable.fortyers);
}
 

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

  holder.awayTeamImageView.setBackgroundResource(R.drawable.game.getaBackground());
 

Но это приводит к ошибке

Как я могу динамически настроить фоновый ресурс ImageView?

Обновить:

Я приложил скриншот желаемого эффекта.

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

введите описание изображения здесь

Игровой конструктор:

 public Games(DataSnapshot game) {

    this.AwayTeam = game.child("AwayTeam").getValue().toString();
    this.AwayId = Integer.parseInt(game.child("AwayId").getValue().toString());

    this.HomeTeam = game.child("HomeTeam").getValue().toString();
    this.HomeId = Integer.parseInt(game.child("HomeId").getValue().toString());

    this.aBackground = game.child("aBackground").getValue().toString();
    this.hBackground = game.child("hBackground").getValue().toString();

}
 

Комментарии:

1. Поместите getaBackground() метод Games , который возвращает идентификатор извлекаемого ресурса.

2. @CommonsWare у меня есть метод, как мне вернуть идентификатор доступного ресурса?

3. Где-то на этом этапе вам нужно будет связать команду с подходящими ресурсами, такими как название команды и изображение шлема. Итак, возможно, у a Games есть два Team объекта, по одному для home и away . У A Team может быть a getTeamName() , который возвращает строковый идентификатор ресурса имени команды, и a getTeamHelmet() , который возвращает идентификатор ресурса для рисования шлема. Где-нибудь ( League одиночка?) вы создадите основной список команд (например, новую команду(R. string.team_name_phl, R. drawable.team_helmet_phl); ). Now, your у игр есть доступ к идентификаторам для рисования для обоих шлемов.

Ответ №1:

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

Если это что-то, повторно используемое в нескольких местах, и порядок согласован, вы также можете перейти к перечислению, чтобы получить идентификатор для рисования с точки зрения определенного ключа по вашему выбору. Возможно, вам потребуется определить ключ, используя условие «когда» в соответствии с позицией, если это действительно зависит от позиции.

Надеюсь, это сработает!

Комментарии:

1. Я добавил обновление и скриншот, поэтому я не думаю, что ваше предложение сработает для меня, так как список будет отличаться от недели к неделе, поскольку он основан на еженедельном расписании.

2. Если это так динамично, вы можете получить свои изображения удаленно, где вы можете возвращать разные изображения в зависимости от недели. Любая простая служба базы данных, такая как firebase, позволит вам хранить определенные имена для ваших изображений, и вы можете хранить одни и те же изображения в облаке в общедоступном месте. Затем используйте любую простую стороннюю библиотеку для загрузки изображения, используя имена, которые вы получаете из своей базы данных, а также статический URL-адрес, по которому осуществляется доступ к вашим изображениям.

3. понятно, значит, на самом деле нет никакого способа сделать это, используя drawable ресурс, правильно?

4. Я не думаю, что это было бы чем-то эффективным, если бы ваш вариант использования требовал, чтобы у вас каждые две недели было другое изображение!

Ответ №2:

Предполагая Games , что класс должен быть классом модели/данных; таким образом, у вас может быть поле-член int, в котором может храниться идентификатор для каждого экземпляра этого класса, и вы можете создать геттер и сеттер:

 public class Games {

    private int myDrawable;

    public int getMyDrawable() {
        return myDrawable;
    }

    public void setMyDrawable(int myDrawable) {
        this.myDrawable = myDrawable;
    }
    
}
 

Всякий раз, когда вы создаете Games объекты, вы можете установить идентификатор рисуемого изображения с помощью setMyDrawable(R.drawabe.foo) .. Вероятно, вы можете изменить Games конструктор, чтобы он принимал параметр int, который вы можете установить myDrawable .

Затем в RecyclerView:

 @Override
public void onBindViewHolder(GameViewHolder holder, int position) {

    final Games game = gameList.get(position);
    holder.awayTeamImageView.setBackgroundResource(game.getMyDrawable());

}

 

Обновить:

 public class Games {

    private int homeTeamImage, awayTeamImage;

    public int getHomeTeamImage() {
        return homeTeamImage;
    }

    public void setHomeTeamImage(int homeTeamImage) {
        this.homeTeamImage = homeTeamImage;
    }


    public int getAwayTeamImage() {
        return awayTeamImage;
    }

    public void setAwayTeamImage(int awayTeamImage) {
        this.awayTeamImage = awayTeamImage;
    }

    public Games(DataSnapshot game, int homeTeamImage, int awayTeamImage) {

        //... rest of code

        this.homeTeamImage = homeTeamImage;
        this.awayTeamImage = awayTeamImage;

    }

}
 

Но с точки зрения ООП я бы предположил, что у вас может быть класс команды, который имеет либо свойства команды, такие как изображение, имя,…. и т.д., И Games класс может быть контроллером игры, а не создавать экземпляры команды.

Комментарии:

1. В какой — то степени это у меня есть. часть, которую я путаю, связана с комментарием, на который вы ссылаетесь в моем конструкторе, setMyDrawable . Я обновил свой вопрос, чтобы отразить мой конструктор.

2. @Learn2Code Просто интересно, хотите ли вы установить как домашние, так и удаленные изображения одинаково

3. Да, это было бы нормально.

4. Я пытаюсь выполнить следующее, но всегда получаю 0 в качестве идентификатора. Integer drawableId = Resources.getSystem().getIdentifier(aTeam, "R.drawable", getPackageName); но, как я уже сказал, это, похоже, не работает?!

5. @Learn2Code Пожалуйста, взгляните на UPDATE раздел. Вы должны получить рисованный идентификатор только с помощью R.drawable.my_resource_id

Ответ №3:

Не усложняйте ситуацию слишком сильно. Просто используйте простой подход. Использование HashMap должно быть просто прекрасным.

 Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Cincinnati", R.drawable.red_striped_helmet);
map.put("Cleveland", R.drawable.red_helmet);
map.put("New York", R.drawable.blue_helmet);
map.put("Chicago", R.drawable.dark_blue_helmet);
map.put(homeTeam, homeId);
...
holder.awayTeamImageView.setBackgroundResource(map.get("New York"));
// holder.awayTeamImageView.setBackgroundResource(map.get(homeTeam));
 

Ответ №4:

Другой подход, который может вам помочь, — это использование getIdentifier из строки. Для этого у вас есть имя фоновой строки, такое же, как у вашего ресурса. например, если вы хотите показать ic_menu_camera , то ваша aBackground строка должна быть такой же.

Пример игрового класса:

 public class Game {

    String aBackground;

    public Game(String aBackground) {
        this.aBackground = aBackground;
    }

    public String getaBackground() {
        return aBackground;
    }

    public void setaBackground(String aBackground) {
        this.aBackground = aBackground;
    }
}
 

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

 //set the background name that you want same as name in your drawable folder
        // without any extension .png or .xml. Just name should be there
        Game game = new Game("ic_menu_camera");
        ImageView imageView = findViewById(R.id.imageView);
        //get the id by name using this
        /*  @param name The name of the desired resource.
             * @param defType Optional default resource type to find, if "type/" is
             *                not included in the name.  Can be null to require an
             *                explicit type.
             * @param defPackage Optional default package to find, if "package:" is
             *                   not included in the name.  Can be null to require an
             *                   explicit package.
             * 
             * @return int The associated resource identifier.  Returns 0 if no such
             *         resource was found.  (0 is not a valid resource ID.)
             * */
        int resId = getResources().getIdentifier(game.getaBackground(), "drawable",getPackageName());
        // then set that id to your image
        imageView.setBackgroundResource(resId);