ViewPager 适配器缓存

ViewPager

xml:
<android.support.v4.view.ViewPager
android:id="@+id/m_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
java:
ViewPager mPager = (ViewPager) findViewById(R.id.m_pager);
定义适配器:
class MyPagerAdapter extends PagerAdapter {
private int[] resIds = { R.drawable.image1, R.drawable.image2,
R.drawable.image3, R.drawable.image4, R.drawable.image5 };
private ImageView[] views;
public MyPagerAdapter() {
views = new ImageView[resIds.length];
for (int i = 0; i < resIds.length; i++) {
views[i] = createImageView(resIds[i]);
}
}

// 配置页面数量

@Override
public int getCount() {
return resIds.length;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
//  销毁 -- 当视图从缓冲中移除出去时触发
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Log.e("m_tag","destroyItem:"+position);
// 获取移除的视图
ImageView iv = views[position];
container.removeView(iv);
}
//  初始化 -- 当有新的内容进入缓冲区时触发
@Override
public Object instantiateItem(ViewGroup container, int position) {
Log.e("m_tag","instantiateItem:"+position);
ImageView iv = views[position];
container.addView(iv);
return iv;
}
private ImageView createImageView(int resId) {
ImageView iv = new ImageView(ViewPagerActivity.this);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
iv.setLayoutParams(lp);
//  显示的图片
iv.setImageResource(resId);
iv.setScaleType(ScaleType.CENTER_CROP);
return iv;
}
}

设置适配器

MyPagerAdapter adapter = new MyPagerAdapter();
mPager.setAdapter(adapter);
页面滑动监听
//ViewPager 页面滑动监听
mPager.setOnPageChangeListener(new OnPageChangeListener() {
// 当选中某个页面时触发(确认显示的新页面)
@Override
public void onPageSelected(int position) {
Log.e("m_tag", "onPageSelected:"+position);
((RadioButton)mGroup.getChildAt(position)).setChecked(true);
}
// 正在滑动中
//position 表示滑动中的第一个页面的下标
//offset 滑动中第一个页面的偏移量 (0-1)
//offsetInPixels 滑动的第一个页面在屏幕外面的像素
@Override
public void onPageScrolled(int position, float offset, int offsetInPixels) {
Log.e("m_tag", "onPageScrolled:"+position+" offset:"+offset+" offsetInPixels:"+offsetInPixels);
}
//1 表示开始拖动 2 表示停止拖动
@Override
public void onPageScrollStateChanged(int state) {
Log.e("m_tag", "state:"+state);
}
});
ViewPager 页面设置
mPager.setCurrentItem(0, true); // 设置显示的页面下标
mPager.getCurrentItem() 获取当前显示的下标
mPager.setPageMargin(20); // 设置页面间距
ViewPager 适配器缓存
原理:在显示的时候将位置和视图对象记录起来,在销毁视图时将要销毁的视图从显示记录中移除出去,将移除出去的视图对象添加到缓存队列中,以便于
下一个初始的时候从缓存中直接获取
public class XPagerAdapter extends PagerAdapter {
// 显示的视图
private Map<Integer,View> showViews;
// 缓存队列
private LinkedList<View> caches;
// 数据源
private int[] resIds = { R.drawable.image1, R.drawable.image2,
R.drawable.image3, R.drawable.image4, R.drawable.image5 };
private Context context;
public XPagerAdapter(Context context){
this.context = context;
showViews = new HashMap<Integer, View>();
caches = new LinkedList<View>();
}
@Override
public int getCount() {
return resIds.length;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0==arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 获取要移除的视图(之前显示过的)
View v = showViews.get(position);
container.removeView(v);
// 将移除的视图对象记录起来
caches.addLast(v);
showViews.remove(position);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 给数据配置显示视图
ImageView iv;
// 如果缓存区中有视图,可以直接拿来显示
if(!caches.isEmpty()){
iv = (ImageView) caches.removeFirst();
}else{
iv = createImageView();
}
iv.setImageResource(resIds[position]);
container.addView(iv);
// 将当前显示的视图用一位置记录起来
showViews.put(position, iv);
return iv;
}
private ImageView createImageView() {
ImageView iv = new ImageView(context);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
iv.setLayoutParams(lp);
iv.setScaleType(ScaleType.CENTER_CROP);
return iv;
}
}

Fragment

Android3.0 之后提出的新功能,低版本使用 v4 包中提供的 Fragment 以及 FragmentActivity 来实现碎片化布局
作用:分担 Activity 的压力,可以灵活轻巧的嵌入到 Activity 中,由 Activity 管理哪个显示哪个隐藏,实现多业务的展示效果
Fragment 不能单独使用,必须要嵌入到 Activity 中由 Activity 管理
Fragment 添加到 Activity 的方式
xml 中添加,静态注册
//ListActivity ,自带一个 ListView
public class LeftFragment extends ListFragment {
private String[] items = { "Java 基础 ", "Java 高级编程 ", " 数据库 ", "Android 基础 ",
"Android 进阶 ", " 项目实战 ", " 项目管理 " };
//  当前 Fragment 要显示的布局
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
//  当布局加载完毕时触发
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ArrayAdapter<String> adapter= new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1,items);
// 给自带的 ListView 设置适配器
setListAdapter(adapter);
}
//ListFragment 中自带的 ListView 的 item 点击监听
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
String str = items[position];
Toast.makeText(getActivity(), " 点击了: "+str, Toast.LENGTH_SHORT).show();
}
}
在 Activity(FragmentActivity) 的布局中使用 fragment 标签添加
<fragment
android:id="@+id/fragment_left"
android:layout_width="200dp"
android:layout_height="match_parent"
android:name="com.xykj.fragment.LeftFragment" />
注意:低版本 Activity 需要继承 FragmentActivity
public class MyActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_my);
}
}
Java 中添加
1 、定义内容显示的碎片对象
public class RightFragment extends Fragment {
public static RightFragment newInstance(String str,int position){
RightFragment f = new RightFragment();
Bundle b = new Bundle();
b.putString("content", str);
b.putInt("pos", position);
// 设置内部参数 ( 只能在显示之前使用 )
f.setArguments(b);
return f;
}
// 配置 Fragment 的布局
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_right, null);
return layout;
}
// 布局创建成功
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
TextView tv = (TextView) view.findViewById(R.id.tv);
// 显示内容
// 获取内部参数中的内容
String content = getArguments().getString("content");
tv.setText(content);
}
// 获取当前碎片显示的下标
public int getIndex(){
return getArguments().getInt("pos");
}
}
2 、获取 FragmentManager 管理碎片
//  获取碎片管理器
FragmentManager fm = getFragmentManager();
//  检测布局中右侧(内容区)是否有内容碎片在显示
RightFragment fragment = (RightFragment) fm
.findFragmentById(R.id.content);
if (fragment == null || position != fragment.getIndex()) {
//  如果有则判断显示的下标跟当前要显示的是不是一样的
//  不一样则替换新的内容进来
//  如果没有内容显示,显示新内容
fragment = RightFragment.newInstance(str, position);
// 获取碎片操作工具(对碎片进行显示、隐藏、替换、添加、移除、注册、取消注册)
FragmentTransaction ft = fm.beginTransaction();
// 添加替换动画
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
ft.replace(R.id.content, fragment); // 替换新的碎片进来
ft.commit();
}
注意: ft.commit() 的提交事务的操作必须在 Activity 保存状态之前使用,如果在状态保存之后,那么需要使用 ft.commitAllowingStateLoss() 提交事务
Fragment 操作时可以将操作添加回退栈
// 回退栈
ft.addToBackStack(null);
添加回退栈可以实现按返回键回到上一个 Fragment 效果
Java 动态管理 ( 选项卡 )
// 假设显示过的 Fragment 对象,我都记录起来,当记录为 null 则表示没显示过,当记录非 null 表示显示过
private Fragment[] fragmens; // 记录曾经显示过的 Fragment 对象
// 记录当前显示的下标
private int currentIndex=-1;
....Activity onCreate...
// 默认显示 0
showFragment(0);
............
/**
*  根据下标显示新的内容 (0 显示消息, 1 好友, 2 动态 )
* @param index
*/
private void showFragment(int index){
// 新的页面跟当前的页面不一样
if(index != currentIndex){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// 隐藏旧的 显示新的 ( 如果有过显示,恢复,如果没有过显示,创建,添加 )
if(currentIndex!=-1){
ft.detach(fragmens[currentIndex]); // 取消关联 ( 会导致 Fragment 的视图销毁 )
}
// 显示新的
if(fragmens[index]!=null){
ft.attach(fragmens[index]); // 恢复关联 ( 到让 Fragment 重新创建视图 )
}else{
// 第一次需要显示
fragmens[index]=createFragment(index);
// 第一次显示出来 ( 添加到容器 )
ft.add(R.id.content, fragmens[index]);
}
ft.commit();
currentIndex = index;
}
}
private Fragment createFragment(int index){
switch (index) {
case 0:
return new FragmentMsg();
case 1:
return new FragmentFriend();
case 2:
return new FragmentMe();
}
return null;
}
退出 Activity 时记得移除曾经显示过的内容
@Override
protected void onDestroy() {
// 移除曾经显示过的 Fragment
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
for(Fragment f : fragmens){
if(null != f){
ft.remove(f);
}
}
// 提交事务,允许状态丢失也要提交
ft.commitAllowingStateLoss();
super.onDestroy();
}

Fragment 添加到 Activity 中的方式

xml 中使用 fragment 标签来添加
Java 中 FragmentManager 来操作
Activity 中管理内部的 Fragment 的 Manager 获取方式
Fragment 中:
getFragmentManager()
FragmentActivity 中:
getSupportFragmentManager()
Fragment 中管理子 Fragment :
getChildFragmentManager()
Fragment 生命周期
xml 添加的方式,生命周期情况
Activity                      Fragment
onCreate                      onAttach
onCreate
onCreateView
onActivity                    Create
onStart                       onStart
onResume                      onResume
onPause                       onPause
onStop                        onStop
onDestroy                     onDestroyView
onDestroy
onDettach

动态管理:


replace :等效于 add 新的 remove 旧的
旧的: onPause 、 onStop 、 onDestroyView
新的: onAttach 、 onCreate 、 onCreateView 、 onActivityCreate 、 onStart 、 onResume
旧的: onDestroy 、 onDettach
detach 、 attach :旧的会销毁视图,新的创建视图
show 、 hide :不影响生命周期
ViewPager+Fragment
可以使用 FragmentPagerAdapter(attach 和 dettach) , FragmentStatePagerAdapter(add 和 remove) 来配置 Fragment 在 ViewPager 中的显示
class MyAdapter extends FragmentPagerAdapter {
private Fragment[] fs;
public MyAdapter(FragmentManager fm) {
super(fm);
fs = new Fragment[] { RightFragment.newInstance(" 碎片 0", 0),
RightFragment.newInstance(" 碎片 1", 1),
RightFragment.newInstance(" 碎片 2", 2),
RightFragment.newInstance(" 碎片 3", 3),
RightFragment.newInstance(" 碎片 4", 4) };
}
@Override
public Fragment getItem(int position) {
return fs[position];
}
@Override
public int getCount() {
return fs.length;
}
}
...
ViewPager mPager = (ViewPager) findViewById(R.id.m_pager);
MyAdapter adapter = new MyAdapter(getSupportFragmentManager());
mPager.setAdapter(adapter);
Fragment 跳转到 Activity
s Intent it = new Intent(getActivity(), ViewPagerFragmentActivity.class); startActivity(it); 第二种
Intent it2 = new Intent(getActivity(), Activity02.class);
startActivityForResult(it2, 101);
重写 onActivityResult 方法接收结果
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.e("m_tag","resultCode:"+resultCode);
if (requestCode == 101) {
if (resultCode == Activity.RESULT_OK) {
String str = data.getStringExtra("result");
tv.setText(str);
} else {
tv.setText(" 用户取消 ");
}
}
}
注意 Fragment 依赖的 Activity 中的 onActivityForResult 的 super.onActivityResult(requestCode, resultCode, data) 方法需要保留,否则信息传不到 Fragment 中

猜你喜欢

转载自blog.csdn.net/AHAI1078766113/article/details/81632360