给刘同学的文档-0
一、解决方法
首先,因为需求需要在切换成竖屏以后再显示以前的图片,那么以前点击的图片就需要保存下来
此时先声明一个中间变量tempImage来存储视图的ID,如下,此变量声明在MainActivity里,作为全局变量。
private int tempImage=0;//作为一个中间变量,使得Fragment生命周期过后也可以拿到原先视图的ID
然后再使用如下这个函数,这个函数的作用是保存Activity的状态,让Activity生命结束后也可以保存数据。
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("Saved tempImage:"+tempImage);
outState.putInt("TEMPIMAGE",tempImage);//第一个参数是key,就是说tempImage以什么名字保存下来
outState.putInt("TEMPTXT",tempTxt);//这个不用也没事
}
每次进入Activity的时候需要把tempImage取出来,此句话写在MainActivity的onCreate()函数里的savedInstanceState是作为Bundle 的参数写在onCreate()里的,所以直接可以用。
if(savedInstanceState!=null)
tempImage=savedInstanceState.getInt("TEMPIMAGE");//每次创建视图都要把tempImage更新
此时就已经做完准备工作了,然后就是最重要的步骤了,根据tempImage这个中间变量来从Fragment里面找到对应的ImageView,再在Activity新的生命周期的时候,用这个ImageView的图片资源替换掉上面的大图。
二、生命周期
如果不是经历了血的教训,我不会认为生命周期那么重要,在一个Fragment里面,必须在执行了onCreateView()之后才会创建视图,这时才能使用View.getView().findViewById()去得到对应的ImageView,前面我一直在onCreate()里面去试图得到视图所以一直报空指针异常(蠢笨如我orz
而在Activity里面要得到Fragment,需要先在MainActivity()里实例化一个Fragment对象,比如我的下面的小视图的名字叫TinyFragment,所以代码如下
private Fragment tiny;
然后在onCreate()里面实例化
tiny = new TinyFragment();
但这个tiny在屏幕旋转过后会被onDestroyView()掉,所以需要注意在屏幕旋转回正常的时候需要在合适的生命周期去拿到tiny对应的资源
三、最后的解决步骤
因为前面讲了,必须在onCreateView()之后Fragment的View才会创建,所以在MainActivity里就只有在onStart()函数里实现替换大图的功能了,代码如下(我写了很多System.out.println(),是作为调试用的,你可以不用写,但是写了之后看控制台的日志会对Activity的生命周期很清楚
@Override
public void onStart(){
super.onStart();
if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){//这句就是书上的,表示判断此时的状态是竖屏,因为在横屏的时候tiny被销毁了,它不出现,所以如果横屏的时候再去拿View就会报空指针异常
if(tempImage!=0){//这句也是防止空指针异常
System.out.println("onStart tempImage: "+tempImage);
ImageView tpView=tiny.getView().findViewById(tempImage);//tpView作为临时变量,保存从tiny里面得到的ImageView
if(tpView==null){
System.out.println("临时视图为空!");
}else{
System.out.println("临时视图不为空!");
showImg.setImageDrawable(tpView.getDrawable());//这句就是更换大图的图片资源,showImg是啥下面再说
}
}else{
System.out.println("进入了onStart但是int为空");
}
}else {
System.out.println("onStart横屏不调用");
}
}
然后showImg就是
private ImageView showImg;
然后在后面下面这句写在onCreate里(其实就是书上那样写
showImg=(ImageView)findViewById(R.id.imageView_show);
然后写到这里的时候,我突然想到了,既然showImg都可以在onCreate里面拿到视图,那为啥不能从tinyFragment里面拿到视图呢,然后我去尝试了一下,报空指针异常了,完了,又是知识盲区(依稀记得我第一次尝试的时候,好像就是这样想的,现在又疑惑了)
好了写完了
四、tempImage的解决方案
初步想法是在TinyFragment的onActivityCreated()里写一个回调函数,然后把此时的img传送给MainActivity,再由这个函数来实现
tempImage = img.getId();
在MainActivity里class后面加上
public class MainActivity extends FragmentActivity implements TinyFragment.ImageClickedListener
在TinyFragment里写监听接口ImageClickedListener
public interface ImageClickedListener{
public void updateTempImage(ImageView img);
}
然后全局变量声明一个mCallback的对象,写在小视图的java文件里
ImageClickedListener mCallback;
在你的小视图的onActivityCreated()里的onClick()里面写一个updateTempImage的回调,注意前面的try里写的mCallback=(ImageClickedListener)getActivity();然后onClick()里面写mCallback.updateTempImage((ImageView)view);
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
try{
mCallback=(ImageClickedListener)getActivity();
}catch (ClassCastException e){
throw new ClassCastException(getActivity().toString()+"must implement ImageClickedListener ");
}
for(int i=0;i<imgId.length;i++){
View view = getView();
if(view==null){
//System.out.println("view is null");
}else {
//System.out.println("view is not null");
tinyImage = view.findViewById(imgId[i]); //findViewById返回为NULL
}
if(tinyImage!=null)
tinyImage.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
mCallback.updateImage((ImageView)view);
mCallback.updateTempImage((ImageView)view);
}
});
}
}
然后在MainActivity里声明
public void updateTempImage(ImageView img){
tempImage = img.getId();
System.out.println("在新函数中更新 "+tempImage);
}
——二仙桥内马尔给AYU的题解