【问题标题】:How to dynamically reference resources in the R.drawable folder in Android?如何在Android中动态引用R.drawable文件夹中的资源?
【发布时间】:2021-06-12 15:23:45
【问题描述】:

我的适配器有以下代码:

@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();

}

【问题讨论】:

  • Games 上放置一个getaBackground() 方法,返回一个可绘制资源ID。
  • @CommonsWare 我有方法,如何返回可绘制资源 id?
  • 在某个地方,您需要能够将团队与合适的资源相关联,例如团队名称和头盔图像。所以,也许Games 有两个Team 对象,homeaway 各有一个。 Team 可以有一个 getTeamName() 返回团队名称的字符串资源 ID,还有一个 getTeamHelmet() 返回头盔的可绘制资源 ID。在某个地方(Leaguesingleton?)您可以创建团队的主名单(例如,new Team(R.string.team_name_phl, R.drawable.team_helmet_phl);). Now, your Games` 可以访问两个头盔的可绘制 ID。

标签: java android android-studio


【解决方案1】:

创建一个包含可绘制对象 id 的字符串列表,使它们保持与位置同步的顺序,然后在设置可绘制对象时根据列表中的位置获取 id。

如果它在多个地方重复使用并且顺序一致,您还可以使用 Enum 来根据您选择的某个键获取可绘制 id。如果它真的依赖于位置,您可能需要根据位置使用 when 条件来计算键。

希望有效!

【讨论】:

  • 我已经添加了更新和屏幕截图,所以我认为您的建议对我不起作用,因为列表每周都会有所不同,因为它基于每周的时间表。
  • 如果它是动态的,您可能希望远程获取您的图像,在那里您可以根据一周返回不同的图像。任何简单的数据库服务(如 firebase)都允许您为图像存储某些名称,并且您可以将相同的图像保存在可公开访问的位置云中。然后使用任何简单的第 3 方库使用从数据库中获取的名称以及访问图像的静态 URL 来加载图像。
  • 明白了,所以真的没有办法使用drawable 资源来做到这一点,对吗?
  • 如果您的用例要求您每隔一周使用不同的图像,我认为这不是有效的方法!
【解决方案2】:

假设Games 类应该是模型/数据类;所以你可以有一个 int 成员字段,可以为这个类的每个实例存储可绘制的 id,并创建 getter 和 setter:

public class Games {

    private int myDrawable;

    public int getMyDrawable() {
        return myDrawable;
    }

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

每当您构造Games 对象时,您都可以使用setMyDrawable(R.drawabe.foo) 设置可绘制图像ID。也许您可以修改Games 构造函数以接受可以将myDrawable 设置为的int 参数。

然后在 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;

    }

}

但就 OOP 而言,我建议您可以有一个 Team 类,它具有团队属性,如图像、名称、....等,而 Games 类可以是游戏的控制器,而不是构建团队实例。

【讨论】:

  • 在某种程度上我有。我感到困惑的部分是您在我的构造函数中引用的注释setMyDrawable。我更新了我的问题以反映我的构造函数。
  • @Learn2Code 只是想知道您是否想以相同的方式设置主场和客场图像
  • 是的,没关系。
  • 我正在尝试以下方法,但总是将 0 作为 id。 Integer drawableId = Resources.getSystem().getIdentifier(aTeam, "R.drawable", getPackageName); 但正如我所说,它似乎不起作用?!
  • @Learn2Code 请查看UPDATE 部分。您应该只使用 R.drawable.my_resource_id 获得可绘制的 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;
        }
    }
    

    然后像这样使用它。阅读 inline cmets 详细了解。

    //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);
    

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 2010-09-06
      • 2016-08-14
      • 2013-11-05
      • 2013-04-06
      • 1970-01-01
      相关资源
      最近更新 更多