【问题标题】:use of multiple <include /> tags in layout with ButterKnife在 ButterKnife 布局中使用多个 <include /> 标签
【发布时间】:2015-08-08 03:26:20
【问题描述】:

我有一个布局,其中我多次包含相同的子布局,每个子布局都有不同的角色:

<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>

如果我以这种方式找到视图,它会起作用:

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

我现在在我的项目中引入 ButterKnife,我希望我可以简单地注释每个视图(以下显然不起作用,我可以看到原因)并稍后使用每个包含的布局根注入它们:

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

但是,这样做会导致我在第二次注入时出现此错误:

错误:(81, 13) 错误: 尝试使用 @InjectView 在“mEcoSeekArc”上注入 ID 2131493185。

我的问题是:有没有办法在这种情况下使用 ButterKnife?

【问题讨论】:

    标签: android butterknife


    【解决方案1】:

    我的回答和 Budius 提出的想法是一样的,我在 ButterKnife 的github repo 的一个相关问题上找到了它。原作者是 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;
        }
    }
    

    MainAcitvity 的 XML:

    <!--...-->
    <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:

    <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>
    

    就是这样!

    我运行的时候,虽然id是一样的,但是因为我复用了,所以TextView里面的文字不一样了。

    【讨论】:

      【解决方案2】:

      您可以像这样使用某种类型的子容器:

      public static class SettingsArcLayout {
        @InjectView(R.id.settings_text) public TextView mEcoText;
        @InjectView(R.id.settings_leaf_img) public ImageView mComfortLeaf;
        // etc...
      }
      

      那么你就有了

      SettingsArcLayout layout1 = new SettingsArcLayout();
      SettingsArcLayout layout2 = new SettingsArcLayout();
      

      然后:

      ButterKnife.inject(this); // inject eco and cmf
      ButterKnife.inject(layout1, eco);
      ButterKnife.inject(layout2, cmf);
      

      通过这个类你可以使用:

      layout1.mEcoText.setText(... etc
      

      【讨论】:

      • 以这种方式有点违背了使用 标签的目的,虽然...
      • 我同意它并不像它应该的那样理想和自动,我只是在寻找解决您问题的方法。但是你仍然在编写更少的代码,更多的模块化代码,你仍然可以使用 ButterKnifeZelezny 插件 (github.com/avast/android-butterknife-zelezny) 自动生成这个子容器。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2017-09-23
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多