Navigation基本概念与基本实现
NavHost是一个容器,用于存放每一个页面(,NavHost同时也是一个控制器)。Fragment是之前就有的概念。NavController用于控制导航逻辑。NavGraph可以使得设置导航路线十分方便。
创建NavGraph
NavGraph是资源文件,右击res文件夹可以新建类型是Navigation的文件。
可以在图形界面中增加fragment、设置fragment的跳转关系,还能设置跳转的动画。
在NavGraph中还需要设置NavHost,也就是这个NavGraph的归属,需要在activity的布局文件中添加container-NavHostFragment,添加的同时选择刚刚创建的NavGraph就完成了绑定。
到此为止fragment已经别添加进了activity中,仍需要设置按钮以实现跳转逻辑。
在按钮的监听事件中设置跳转逻辑
跳转就是获取这个navigation的controller,利用这个controller来实现跳转,具体代码是:
getView().findViewById(R.id.button2).setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_detailFragment_to_homeFragment));
这个是紧凑写法,也可以按照普通的写法来。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button button=getView().findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavController controller= Navigation.findNavController(view);
controller.navigate(R.id.action_homeFragment_to_detailFragment2);
}
});
}
为非start的fragment设置标题栏后退键
首先是开启后退键:
//activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavController controller= Navigation.findNavController(this,R.id.fragment);
NavigationUI.setupActionBarWithNavController(this,controller);
}
为后退键添加响应:
//activity @Override public boolean onSupportNavigateUp() { NavController controller=Navigation.findNavController(this,R.id.fragment); return controller.navigateUp(); }
Navigation数据传递
静态的Argument传递
直接在navigation.xml文件中添加。可以在目标fragment中设置Argument,也可以在action中设置。
动态传递
在源fragment中的controller的跳转方法中增加bundle参数。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getView().findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EditText editText=getView().findViewById(R.id.editTextTextPersonName);
String string=editText.getText().toString();
if (TextUtils.isEmpty(string)){
Toast.makeText(getContext(),"请输入名字",Toast.LENGTH_SHORT).show();
return;
}
Bundle bundle=new Bundle();
bundle.putString("my_name",string);
NavController controller=Navigation.findNavController(view);
controller.navigate(R.id.action_homeFragment_to_detailFragment,bundle);
}
});
}
目标fragment接收数据
和旧的写法一样。
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String string=getArguments().getString("name");
String string2=getArguments().getString("my_name");
TextView textView =getView().findViewById(R.id.textView);
textView.setText(string2);
}
Navigation跳转动画
跳转动画是可以直接在navigation.xml文件中的箭头上设置的,有默认的一些动画效果。
自定义动画需要创建类型为animation的资源文件,例如:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="1000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"/>
<rotate
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360"/>
</set>
实现效果:
将Navigation和VIewModel结合
databinding一般只绑定数据相关的,和逻辑相关的还是放到activity/fragment中。
在Navigation中使用ViewModel之后连数据都不需要通过bundle传入了,除此之外在onCreateView中返回的不再是之前的
inflater.inflate(R.layout.fragment_main, container, false);
而是
return binding.getRoot();
此外,剩下来的代码就是之前所学的东西的结合。
//MasterFragment.java
public class MasterFragment extends Fragment {
}
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
// return inflater.inflate(R.layout.fragment_main, container, false);
final MyViewModel myViewModel=new ViewModelProvider(getActivity(),new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
FragmentMainBinding binding= DataBindingUtil.inflate(inflater,R.layout.fragment_main,container,false);
binding.setData(myViewModel);
binding.setLifecycleOwner(getActivity());
binding.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavController controller= Navigation.findNavController(view);
controller.navigate(R.id.action_masterFragment_to_detailFragment);
}
});
binding.seekBar.setProgress(myViewModel.getNumber().getValue());
binding.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
myViewModel.getNumber().setValue(i);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
return binding.getRoot();
}
}
//DetailFragment.java
public class DetailFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
// return inflater.inflate(R.layout.fragment_detail, container, false);
MyViewModel myViewModel=new ViewModelProvider(getActivity(),new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
FragmentDetailBinding binding= DataBindingUtil.inflate(inflater,R.layout.fragment_detail,container,false);
binding.setData(myViewModel);
binding.setLifecycleOwner(getActivity());
binding.button4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavController controller= Navigation.findNavController(view);
controller.navigate(R.id.action_detailFragment_to_masterFragment);
}
});
return binding.getRoot();
}
}