1. ViewPager使用
(1)基本使用
自定义Adapter,继承 PagerAdapter
private class MyAdapter extends PagerAdapter {
private final int Index_Count = 2;
private View[] views = new View[Index_Count];
@Override
public int getCount() {
return Index_Count;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
/**
* 初始化 View 布局
* 可以在这里,读取入布局后,
* 初始化View
* @param container container
* @param position 位置
* @return view
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
if (views[position]==null) {
View convertView = LayoutInflater.from(container.getContext())
.inflate(R.layout.single_recycler_layout, null);
container.addView(convertView);
views[position] = convertView;
}
return views[position];
}
/**
* 销毁UI
* @param container container
* @param position pager 标号
* @param object object
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
复制代码
设置MyAdapter
myAdapter = new MyAdapter();
viewPager.setAdapter(myAdapter);
复制代码
(2)设置 ViewPagerIndicator
参考大神的Demo吧。
(3)Fragment ViewPager
千万不要像(1)一样重写方法,因为 FragmentPagerAdapter 内部已经做好重写了。
public class MyViewPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;
public MyViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragmentList = fragments;
}
@Override
public int getCount() {
return fragmentList.size();
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
}
复制代码
ViewPager viewPager;
List<Fragment> list;
list = new ArrayList<>();
list.add(BlankFragment.newInstance("One"));
list.add(BlankFragment.newInstance("Two"));
list.add(BlankFragment.newInstance("Three"));
MyViewPagerAdapter myAdapter = new MyViewPagerAdapter(getSupportFragmentManager(), list);
viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.setAdapter(myAdapter);
复制代码
2. 设置ViewPager的滑动速度
【参考】
定义Scroller:
Scroller scroller = new Scroller(viewPager.getContext()) {
private int mDuration = 1500;
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy, mDuration);
}
};
复制代码
设置Scroller,因为没有API,需要用反射设置:
try {
Field field = ViewPager.class.getDeclaredField("mScroller");
field.setAccessible(true);
field.set(viewPager, scroller);
} catch (Exception ignored) {
}
复制代码
3. 判断Fragment显示和隐藏
- 使用show和hide来显隐的Fragment,那么通过:
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if(hidden){
//TODO now visible to user
} else {
//TODO now invisible to user
}
}
复制代码
- 在ViewPager中的Fragment,此时候上面的方法不适用
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
//TODO now it's visible to user
} else {
//TODO now it's invisible to user
}
}
复制代码
4. Fragment切换效果
(1)系统自带
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.setTransition(int transit);
// transit参数说明,标准动画设置好后,在Fragment添加和移除的时候都会有。
// 1. FragmentTransaction.TRANSIT_NONE:无动画
// 2. FragmentTransaction.TRANSIT_FRAGMENT_OPEN:标准的打开动画效果
// 3. FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:标准的关闭动画效果
复制代码
(2)自定义
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.in_from_right, R.anim.out_to_left);
复制代码
5. Fragment点击触发Activity布局或者其他的Fragment
原因:Fragment的布局实质是依赖在Activity之上,因为会有事件分发和传递。
解决:
-
XML中给fragment的布局设置,或者在Java代码中设置也可以
android:clickable="true" android:focusable="true" 复制代码
-
给布局设置
onTouch
事件,并返回true,代表拦截此事件。view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; //截断事件的传递 } }); 复制代码
6. Fragment标准写法
Android Studio 新建Fragment模块的时候,示例代码:
public class BlankFragment extends Fragment {
/*声明传入的参数*/
private static final String ARG_PARAM1 = "param1";
private String mParam1;
/*监听器*/
private OnFragmentInteractionListener mListener;
/*必须要一个空的构造方法*/
public BlankFragment() {}
/**
* 使用这个方法进行实例化
* @param param1 参数
* @return fragment
*/
public static BlankFragment newInstance(String param1) {
BlankFragment fragment = new BlankFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
}
/**
* 为了防止屏幕旋转的情况,需要取出参数
* 在 new 的时候去设置好参数
* @param savedInstanceState state
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
}
}
/**
* 在这里初始化好View,获取到控件
* @return View
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_blank, container, false);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* 这个接口由Activity实现,就可以进行通信
* 注意,是在 onAttach 和 onDetach
* 中注册监听和销毁监听
*/
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
}
复制代码
7. ViewPager中Fragment懒加载
【Demo】
- setContentView:获取布局
- initView:进行View控件的绑定
- lazyLoad:懒加载
public abstract class LazyLoadFragment extends Fragment {
protected View rootView;
private boolean isInitView = false;
private boolean isVisible = false;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(setContentView(), container, false);
initView();
isInitView = true;
isCanLoadData();
return rootView;
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
isVisible = true;
isCanLoadData();
}else{
isVisible = false;
}
}
private void isCanLoadData(){
if(isInitView && isVisible ){
lazyLoad();
isInitView = false;
isVisible = false;
}
}
protected abstract int setContentView();
protected abstract void initView();
protected abstract void lazyLoad();
}
复制代码
8. Fragment的生命周期
浅谈Android中的 Fragment、生命周期回调方法 以及使用
Fragment的生命周期和Activity息息相关
onAttach():fragment已经关联到activity,getActivity不为空,与onDetach()对应
onCreate():系统创建fragment的时候回调他,在他里面实例化一些变量,这些个变量主要是:当你暂停、停止的时候,你想保持的数据,他只调用一次。
onCreateView():fragment加载布局
onActivityCreated():Activity中的onCreate方法执行完后调用。与activity有交互的UI操作,再onActivityCreated()中执行,确保Activity已经完成布局。
onStart():和Activity一致,启动Fragment
onResume():fragment可见,获取焦点
onPause():fragment暂停,其他activity获取焦点
onStop():和activity一致, fragment不可见的, 可能情况:activity被stopped了或者 fragment被移除但被,加入到回退栈中,一个stopped的fragment仍然是活着的如果长时间不用也会被移除。
onDestroyView():Fragment中的布局被移除时调用。表示fragemnt销毁相关联的UI布局, 清除所有跟视图相关的资源。然后这个只是识移除视图,并没有销毁而且还没有脱离activity
onDestroy():销毁fragment对象, 跟activity类似了。
onDetach(): Fragment和Activity解除关联的时候调用,脱离activity。
9. 嵌套Fragment
当在 Fragment 中要用到 FragmentManager 的时候一定要记住,使用 getChildFragmentManager()。