Using multiple <include / "> tags in a layout with ButterKnife
I have a layout where I include the same sub-layout several times, each with a different role:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <include android:id="@+id/settings_eco_seekarc" android:layout_width="match_parent" android:layout_height="match_parent" layout="@layout/settings_arc" /> <include android:id="@+id/settings_comfort_seekarc" android:layout_width="match_parent" android:layout_height="match_parent" layout="@layout/settings_arc" /> </LinearLayout> It works if I find the views this way:
View eco = root.findViewById(R.id.settings_eco_seekarc); mEcoSeekArc = (SeekArc) eco.findViewById(R.id.settings_seekarc); mEcoLeaf = (ImageView) eco.findViewById(R.id.settings_leaf_img); mEcoText = (TextView) eco.findViewById(R.id.settings_text); View cmf = root.findViewById(R.id.settings_comfort_seekarc); mComfortSeekArc = (SeekArc) cmf.findViewById(R.id.settings_seekarc); mComfortLeaf = (ImageView) cmf.findViewById(R.id.settings_leaf_img); mComfortText = (TextView) cmf.findViewById(R.id.settings_text); I represent ButterKnife in my project now, and I was hoping that I could simply annotate each point of view (obviously this does not work, and I understand why) and insert them later, using each included root of the layout:
@InjectView(R.id.settings_seekarc) SeekArc mEcoSeekArc; @InjectView(R.id.settings_leaf_img) ImageView mEcoLeaf; @InjectView(R.id.settings_text) TextView mEcoText; @InjectView(R.id.settings_seekarc) SeekArc mComfortSeekArc; @InjectView(R.id.settings_leaf_img) ImageView mComfortLeaf; @InjectView(R.id.settings_text) TextView mComfortText; //then later... View eco = root.findViewById(R.id.settings_eco_seekarc); ButterKnife.inject(this, eco); View cmf = root.findViewById(R.id.settings_comfort_seekarc); ButterKnife.inject(this, cmf); Doing this, however, leads me to this error on the second injection:
Error: (81, 13): attempt to use @InjectView to already entered ID 2131493185 on "mEcoSeekArc".
My question is: is there a way to use ButterKnife in this scenario?
you can use some type of sub-container, for example:
public static class SettingsArcLayout { @InjectView(R.id.settings_text) public TextView mEcoText; @InjectView(R.id.settings_leaf_img) public ImageView mComfortLeaf; // etc... } then you have
SettingsArcLayout layout1 = new SettingsArcLayout(); SettingsArcLayout layout2 = new SettingsArcLayout(); and then:
ButterKnife.inject(this); // inject eco and cmf ButterKnife.inject(layout1, eco); ButterKnife.inject(layout2, cmf); and through this class you can use:
layout1.mEcoText.setText(... etc The idea of my answer is the same as Budius suggested, I found it in a related issue in ButterKnife github repo . Original author - TomazMartins
MainActivity:
public MainActivity extends AppCompatActivity { // 1. First, we declare the layout that was included as a View objects. @BindView( R.id.layout_1 ) View layout_1; @BindView( R.id.layout_2 ) View layout_2; @Override protected void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); setContentView( R.layout.activity_main ); // 2. In here, we bind the included layouts ButterKnife.bind( this ); // 4. Then, we create objects of the type of the IncludedLayout. // In this example the layout reuse the same layout twice, so, there are two // IncludedLayouts. IncludedLayout includedLayout_1 = new IncludedLayout(); IncludedLayout includedLayout_2 = new IncludedLayout(); // 5. We bind the elements of the included layouts. ButerKnife.bind( includedLayout_1, layout_1 ); ButerKnife.bind( includedLayout_2, layout_2 ); // 6. And, finally, we use them. includedLayout_1.displayed_text.setText( "Hello" ); includedLayout_2.displayed_text.setText( "Hey!" ); } // 3. We create a static class that will be an container of the elements // of the included layout. In here we declare the components that // hold this. In this example, there is only one TextView. static class IncludedLayout { @BindView( R.id.displayed_text ) TextView displayed_text; } } XML MainAcitvity:
<!--...--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <include android:id="@+id/layout_1" layout="@layout/included_layout" /> <include android:id="@+id/layout_2" layout="@layout/included_layout" /> </LinearLayout> <!--...--> XML inbound layout:
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/displayed_text"/> </LinearLayout> What is it!
When I ran it, although the identifier was the same because I reused it, the text in the TextView was different.