Android

Android JetPack学习总结(三)

Navigation基本概念与基本实现

NavHost是一个容器,用于存放每一个页面(,NavHost同时也是一个控制器)。Fragment是之前就有的概念。NavController用于控制导航逻辑。NavGraph可以使得设置导航路线十分方便。

创建NavGraph

NavGraph是资源文件,右击res文件夹可以新建类型是Navigation的文件。

image 4

可以在图形界面中增加fragment、设置fragment的跳转关系,还能设置跳转的动画。

image 5

在NavGraph中还需要设置NavHost,也就是这个NavGraph的归属,需要在activity的布局文件中添加container-NavHostFragment,添加的同时选择刚刚创建的NavGraph就完成了绑定。

image 6

到此为止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中设置。

image 7
动态传递

在源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文件中的箭头上设置的,有默认的一些动画效果。

image 8

自定义动画需要创建类型为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>

实现效果:

GIF 2020 10 11 15 26 26 1

将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();
    }
}

发表评论