2017-07-16 297 views
3

我想使用数据绑定库更改工具栏标题。一切正常,除了BottomNavigationView的倾听者,即我有一个错误:使用数据绑定添加BottomNavigationView的点击监听器

FAILURE: Build failed with an exception. 

* What went wrong: 
Execution failed for task ':app:compileDebugJavaWithJavac'. 
> java.lang.RuntimeException: Found data binding errors. 
****/ data binding error ****msg:Could not resolve viewmodel::onNavigationClick as a listener. 
file:D:\Replacements\app\src\main\res\layout\activity_main.xml 
loc:85:40 - 85:67 
****\ data binding error **** 

,我认为它是由二传手的错名字引起的用于XML属性相关联。在xml BottomNavigationView有app:onNavigationItemSelected,但BottomNavigationView的设置者是setOnNavigationItemSelectedListener,而不是setOnNavigationItemSelected。如果我是对的,解决方案在Android documentation。但是我应该在哪里添加注释?在哪个级别?

换句话说,我应该怎么做才能让ViewModel中的代码能够控制对BottomNavigationView的点击?

以下是文件:

ActivityMain.java

public class ActivityMain extends AppCompatActivity { 

    private ActivityMainViewModel viewModel; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Initiating ViewModel to Activity 
     viewModel = ViewModelProviders.of(this).get(ActivityMainViewModel.class); 

     // Initiating ContentView in Activity 
     setContentView(R.layout.activity_main); 

     // Initiating DataBinding for ContentView in Activity 
     ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); 
     binding.setViewmodel(viewModel); 
    } 
} 

ActivityMainViewModel.java

public class ActivityMainViewModel extends ViewModel { 

    private MutableLiveData<String> toolbarTitle = new MutableLiveData<>(); 

    public String getToolbarTitle() { 
     return toolbarTitle.getValue(); 
    } 

    public void setToolbarTitle(String toolbarTitle) { 
     this.toolbarTitle.setValue(toolbarTitle); 
    } 

    public boolean onNavigationClick(@NonNull MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.navigation_1: 
       setToolbarTitle("title 1"); 
       return true; 
      case R.id.navigation_2: 
       setToolbarTitle("title 2"); 
       return true; 
      case R.id.navigation_3: 
       setToolbarTitle("title 3"); 
       return true; 
     } 
     return false; 
    } 
} 

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?> 
<layout xmlns:android="http://schemas.android.com/apk/res/android"> 

<data> 
    <variable name="viewmodel" type="com.example.example.viewmodel.ActivityMainViewModel"/> 
</data> 

<android.support.constraint.ConstraintLayout 
    ...> 

    <android.support.design.widget.AppBarLayout 
     ...> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/main_toolbar" 
      android:title="@{viewmodel.toolbarTitle}" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:background="@color/new_blue_light" 
      android:minHeight="?attr/actionBarSize" 
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> 

    </android.support.design.widget.AppBarLayout> 

    <FrameLayout 
     ...> 
     ... 
    </FrameLayout> 

    <android.support.design.widget.BottomNavigationView 
     android:id="@+id/navigation" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:background="?android:attr/windowBackground" 
     app:itemIconTint="@drawable/navigation_color_state" 
     app:itemTextColor="@drawable/navigation_color_state" 
     app:layout_constraintBottom_toBottomOf="parent" 
     app:layout_constraintLeft_toLeftOf="parent" 
     app:layout_constraintRight_toRightOf="parent" 
     app:menu="@menu/navigation" 
     app:onNavigationItemSelected="@{viewmodel::onNavigationClick}" 
     tools:layout_constraintBottom_creator="0" 
     tools:layout_constraintLeft_creator="0" 
     tools:layout_constraintRight_creator="0" /> 

</android.support.constraint.ConstraintLayout> 

</layout> 

的唯一的事情,我想d o是创建自定义视图(应用程序运行,但它不会改变工具栏标题,并给出警告:warning: Application namespace for attribute app:onNavigationItemSelected will be ignored.):

@BindingMethods({ 
     @BindingMethod(
       type = BottomNavigationViewBinding.class, 
       attribute = "app:onNavigationItemSelected", 
       method = "setOnNavigationItemSelectedListener" 
     ), 
}) 
public class BottomNavigationViewBinding extends BottomNavigationView{ 

    private OnNavigationItemSelectedListener mSelectedListener; 

    public BottomNavigationViewBinding(Context context) { 
     this(context, null); 
    } 

    public BottomNavigationViewBinding(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public BottomNavigationViewBinding(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    public interface OnNavigationItemSelectedListener { 
     boolean onNavigationItemSelected(MenuItem item); 
    } 

    public void setOnNavigationItemSelectedListener(@Nullable OnNavigationItemSelectedListener listener) { 
     mSelectedListener = listener; 
    } 
} 

回答

2

这个替换您NavigationItemViewBinding类,它会工作:

public class BottomNavigationViewBindingAdapter { 
    @BindingAdapter("onNavigationItemSelected") 
    public static void setOnNavigationItemSelectedListener(
      BottomNavigationView view, OnNavigationItemSelectedListener listener) { 
     view.setOnNavigationItemSelectedListener(listener); 
    } 
} 

这个想法是,你想要使用自定义setter来合并侦听器,这需要比重命名设置侦听器的方法更多的工作。

https://developer.android.com/topic/libraries/data-binding/index.html#custom_setters

+0

非常感谢!有用 –