Using Butterknife to inject an array of views
Asked Answered
T

2

18

Currently I have this array of views:

ImageView activityImageViews[] = {
    (ImageView) rootView.findViewById(R.id.img_activity_1),
    (ImageView) rootView.findViewById(R.id.img_activity_2),
    (ImageView) rootView.findViewById(R.id.img_activity_3),
    (ImageView) rootView.findViewById(R.id.img_activity_4)
};

Is there a way I could use Butterknife to inject all those views? I need to keep them in an array (or in a way so I can iterate over them).

Turtledove answered 17/2, 2014 at 13:35 Comment(1)
Just recently stumbled upon Butterknife so do not know if it supports that directly but why not just inject them individually and collect them in an array or a list inside onCreate?Cristoforo
S
48

Currently it is possible to inject several views as array. From ButterKnife documentation (see VIEW LISTS section)

@InjectViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;

Same thing for multiple click listeners:

@OnClick({ R.id.door1, R.id.door2, R.id.door3 })
public void pickDoor(DoorView door) {
  if (door.hasPrizeBehind()) {
    Toast.makeText(this, "You win!", LENGTH_SHORT).show();
  } else {
    Toast.makeText(this, "Try again", LENGTH_SHORT).show();
  }
}

UPDATE 2017-09-19: Since Butterknife version Version 7.0.0 (2015-06-27) @Bind replaced @InjectView and @InjectViews. But since version Version 8.0.0 (2016-04-25) @Bind was replaced with @BindView and @BindViews for one view and multiple views, respectively. So for now the correct syntax is:

@BindView(R.id.button1) Button button1;
@BindView(R.id.button2) Button button2;

@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;
Soche answered 17/6, 2014 at 17:52 Comment(1)
Cool! Even though I'm not working on that project anymore, it's good to know for future reference so thanks :)Turtledove
H
2

I suppose that the elements added to the Array are dynamically, otherwise you can simply declare them in your header one by one and afterwards add them to the array:

// in the header:
@InjectView(R.id.imageview1) ImageView imageView1;
@InjectView(R.id.imageview2) ImageView imageView2;
@InjectView(R.id.imageview3) ImageView imageView3;

// inside your code:
ImageView activityImageViews[] = {
    imageView1, imageView2, imageView3
};

But however, if the elements are dynamic (in amount of elements/id of elements etc.) the only thing you can do is to use ButterKnife.findById which will spare the ImageView cast - you can't inject them via annotation because Butterknife does not know what to generate/inject on compile time (the information is first available on runtime).

ImageView activityImageViews[] = {
    ButterKnife.findById(view, R.id.img_activity_1),
    ButterKnife.findById(view, R.id.img_activity_2),
    ButterKnife.findById(view, R.id.img_activity_3),
    ButterKnife.findById(view, R.id.img_activity_4)
};
Hendon answered 17/2, 2014 at 13:51 Comment(2)
The second snippet gives Incompatible types. Required: android.widget.ImageView, Found: android.view.View. I'll use your first approach, thank you!Turtledove
Hmm, that's strange. I use ButterKnife 4.0.1 and also the second approach works fine for me. The documentation says [...]It uses generics to infer the return type and automatically performs the cast.Hendon

© 2022 - 2024 — McMap. All rights reserved.