Android ViewPager:重新创建单个特定片段

Android ViewPager:重新创建单个特定片段,android,android-fragments,android-viewpager,Android,Android Fragments,Android Viewpager,我使用带有两个片段的ViewPager:PhotoFragment和GalleryFragment。 如果我滑动到第二个片段(GalleryFragment),我总是想重新创建该片段。 但是当我刷回第一个片段(PhotoFragment)时,我想从内存中提取它 我试图在这个问题上实施解决方案 我使用了notifyDataSetChanged(),并在滑动到第二个片段时覆盖了getItemPosition()以返回位置\u NONE。 当我滑动到第二个片段时,它被正确地重新创建。但是当我扫回第一个

我使用带有两个片段的ViewPager:PhotoFragment和GalleryFragment。
如果我滑动到第二个片段(GalleryFragment),我总是想重新创建该片段。
但是当我刷回第一个片段(PhotoFragment)时,我想从内存中提取它

我试图在这个问题上实施解决方案

我使用了
notifyDataSetChanged()
,并在滑动到第二个片段时覆盖了
getItemPosition()
以返回位置\u NONE。
当我滑动到第二个片段时,它被正确地重新创建。但是当我扫回第一个片段时,我注意到它也被重新创建了

我猜返回位置_NONE会导致删除并重新创建适配器中的所有片段。我是一名Android初学者,不知道如何才能只重新创建第二个片段

带ViewPager的主活动:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ViewPager viewPager = findViewById(R.id.viewpager);
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);

        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i1) {
            }

            @Override
            public void onPageSelected(int i) {
                if (i == 1) {
                    viewPager.getAdapter().notifyDataSetChanged();
                }
            }

            @Override
            public void onPageScrollStateChanged(int i) {
            }
        });

        TabLayout tabLayout = findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }
}
适配器:

public class ViewPagerAdapter extends FragmentStatePagerAdapter {

    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public Fragment getItem(int i) {
        switch (i) {
            case 0:
                return new PhotoFragment();
            case 1:
                return new GalleryFragment();
            default:
                return null;
        }
    }

    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Photo";
            case 1:
                return "Gallery";
            default:
                return null;
        }
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}
照片片段:

public class PhotoFragment extends Fragment {

    private static final int CAMERA_REQUEST_CODE = 0;
    private static final int GALLERY_REQUEST_CODE = 1;
    private ImageView mCapturedImageView;
    private String mCacheFileLocation;
    private File mCacheFolder;
    private File mGalleryFolder;
    private String mImageFileLocation;
    private TextView mMonthText;
    private FrameLayout stickerFrameLayout;
    private static final String TAG = "PhotoFragment";

    public PhotoFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_photo, container, false);

        mMonthText = rootView.findViewById(R.id.monthText);
        mCapturedImageView = rootView.findViewById(R.id.capturedImageView);
        ImageButton mCameraButton = rootView.findViewById(R.id.cameraButton);
        ImageButton mSaveButton = rootView.findViewById(R.id.saveButton);
        stickerFrameLayout = rootView.findViewById(R.id.stickerFrameLayout);
        ImageButton mRainbowButton = rootView.findViewById(R.id.buttonRainbow);
        ImageButton mDancerButton = rootView.findViewById(R.id.buttonDancer);
        ImageButton mGlassesButton = rootView.findViewById(R.id.buttonGlasses);
        ImageButton mHeartButton = rootView.findViewById(R.id.buttonHeart);
        ImageButton mCrownButton = rootView.findViewById(R.id.buttonCrown);
        ImageButton mJorisButton = rootView.findViewById(R.id.buttonJoris);

        mMonthText.setVisibility(View.INVISIBLE);
        createImageFolders();

        View.OnClickListener stickerListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addSticker(v.getId());
            }
        };
        mRainbowButton.setOnClickListener(stickerListener);
        mDancerButton.setOnClickListener(stickerListener);
        mGlassesButton.setOnClickListener(stickerListener);
        mHeartButton.setOnClickListener(stickerListener);
        mCrownButton.setOnClickListener(stickerListener);
        mJorisButton.setOnClickListener(stickerListener);

        mCameraButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showPictureDialog();
            }
        });

        mSaveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                saveImage();
            }
        });

        return rootView;
    }

    private void showPictureDialog() {
        AlertDialog.Builder pictureDialog = new AlertDialog.Builder(getActivity());
        pictureDialog.setTitle("Select Action");
        String[] pictureDialogItems = {"Select photo from device", "Capture photo with camera"};
        pictureDialog.setItems(pictureDialogItems, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which) {
                    case 0:
                        pickImage();
                        break;
                    case 1:
                        takePhoto();
                        break;
                }
            }
        });
        pictureDialog.show();
    }

    private void pickImage() {
        Intent pickImageIntent = new Intent(Intent.ACTION_PICK);
        pickImageIntent.setType("image/*");
        String[] mimeTypes = {"image/jpeg", "image/png"};
        pickImageIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
        pickImageIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
        startActivityForResult(pickImageIntent, GALLERY_REQUEST_CODE);
        mMonthText.setVisibility(View.INVISIBLE);
    }

    private void takePhoto() {
        Intent callCameraApplicationIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (callCameraApplicationIntent.resolveActivity(getActivity().getPackageManager()) != null) {
            File file = null;
            try {
                file = createCacheFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (file != null) {
                Uri photoURI = FileProvider.getUriForFile(getActivity(), "com.jorisvanlaar.employeeofthemonth.fileprovider", file);
                callCameraApplicationIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(callCameraApplicationIntent, CAMERA_REQUEST_CODE);
                mMonthText.setVisibility(View.INVISIBLE);
            }
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == getActivity().RESULT_OK) {
            switch (requestCode) {
                case GALLERY_REQUEST_CODE:
                    Bitmap bitmap = null;
                    if (data.getData() != null) {
                        try {
                            bitmap = BitmapFactory.decodeStream(getActivity().getContentResolver().openInputStream(data.getData()));
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        writeBitmapToFile(bitmap, createCacheFile());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    rotateImage(reduceImageSize());
                    break;

                case CAMERA_REQUEST_CODE:
                    rotateImage(reduceImageSize());
                    break;
            }
        }
    }

    private void createImageFolders() {
        File storageDirectory = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        mCacheFolder = new File(storageDirectory, "cached files");
        if (!mCacheFolder.exists()) {
            mCacheFolder.mkdirs();
        }
        mGalleryFolder = new File(storageDirectory, "Image Gallery");
        if (!mGalleryFolder.exists()) {
            mGalleryFolder.mkdirs();
        }
    }

    @SuppressLint("SimpleDateFormat")
    private File createCacheFile() throws IOException {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String cacheFileName = "IMG_" + timeStamp + "_";
        File image = File.createTempFile(cacheFileName, ".jpg", mCacheFolder);
        mCacheFileLocation = image.getAbsolutePath();
        return image;
    }

    @SuppressLint("SimpleDateFormat")
    private File createImageFile() {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "EMPL_" + timeStamp + "_.jpg";
        File image = new File(mGalleryFolder, imageFileName);
        mImageFileLocation = image.getAbsolutePath();
        return image;
    }

    private void writeBitmapToFile(Bitmap bitmap, File destination) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(destination);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
        } catch (Exception ex) {
            Log.i(TAG, "Error writing bitmap to file");
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    private Bitmap reduceImageSize() {
        int targetImageViewWidth = mCapturedImageView.getWidth();
        int targetImageViewHeight = mCapturedImageView.getHeight();

        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCacheFileLocation, bmOptions);
        int cameraImageWidth = bmOptions.outWidth;
        int cameraImageHeight = bmOptions.outHeight;

        int scaleFactor = Math.min(cameraImageWidth / targetImageViewWidth, cameraImageHeight / targetImageViewHeight);

        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;

        Bitmap photoReducedSizeBitmap = BitmapFactory.decodeFile(mCacheFileLocation, bmOptions);
        return photoReducedSizeBitmap;
    }

    private void rotateImage(Bitmap bitmap) {
        ExifInterface exifInterface = null;
        try {
            exifInterface = new ExifInterface(mCacheFileLocation);
        } catch (IOException e) {
            e.printStackTrace();
        }
        int orientation = 0;
        if (exifInterface != null) {
            orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
        }
        Matrix matrix = new Matrix();
        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                matrix.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                matrix.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                matrix.setRotate(270);
                break;
            default:
        }
        Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        mCapturedImageView.setImageBitmap(rotatedBitmap);
    }

    @SuppressLint("SetTextI18n")
    private void saveImage() {
        Calendar calendar = Calendar.getInstance();
        int currentMonth = calendar.get(Calendar.MONTH);
        MonthCollection monthCollection = new MonthCollection();
        mMonthText.setText("Employee of " + monthCollection.getMonth(currentMonth));
        mMonthText.setVisibility(View.VISIBLE);

        Bitmap bitmap = Bitmap.createBitmap(stickerFrameLayout.getWidth(), stickerFrameLayout.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        stickerFrameLayout.draw(canvas);

        writeBitmapToFile(bitmap, createImageFile());
        Toast.makeText(getActivity(), "Image saved!", Toast.LENGTH_SHORT).show();
    }

    private void addSticker(int id) {
        StickerImageView sticker = new StickerImageView(getActivity());
        switch (id) {
            case R.id.buttonRainbow:
                sticker.setImageDrawable(getResources().getDrawable(R.drawable.sticker_rainbow));
                break;
            case R.id.buttonDancer:
                sticker.setImageDrawable(getResources().getDrawable(R.drawable.sticker_dancer));
                break;
            case R.id.buttonGlasses:
                sticker.setImageDrawable(getResources().getDrawable(R.drawable.sticker_sunglasses));
                break;
            case R.id.buttonHeart:
                sticker.setImageDrawable(getResources().getDrawable(R.drawable.sticker_heart));
                break;
            case R.id.buttonCrown:
                sticker.setImageDrawable(getResources().getDrawable(R.drawable.sticker_crown));
                break;
            case R.id.buttonJoris:
                sticker.setImageDrawable(getResources().getDrawable(R.drawable.sticker_joris));
                break;
            default:
                throw new RuntimeException("Unknown button ID");
        }
        stickerFrameLayout.addView(sticker);
    }
}
厨房碎片:

public class GalleryFragment extends Fragment {

    private RecyclerView mRecyclerView;
    private File mGalleryFolder;
    private static int mColumnCount = 3;
    private static int mImageWidth;
    private static int mImageHeight;

    public GalleryFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_gallery, container, false);

        mRecyclerView = rootView.findViewById(R.id.galleryRecyclerView);
        mGalleryFolder = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES + "/Image Gallery");

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        mImageWidth = displayMetrics.widthPixels / mColumnCount;
        mImageHeight = mImageWidth * 4 / 3;

        GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), mColumnCount);
        mRecyclerView.setLayoutManager(layoutManager);

        File[] sortedGalleryFolder = sortFilesToLatest(mGalleryFolder);
        RecyclerView.Adapter imageAdapter = new ImageAdapter(sortedGalleryFolder, mImageWidth, mImageHeight);
        mRecyclerView.setAdapter(imageAdapter);

        return rootView;
    }

    private File[] sortFilesToLatest(File imageDirectory) {
        File[] files = imageDirectory.listFiles();
        Arrays.sort(files, new Comparator<File>() {                                     
            @Override
            public int compare(File o1, File o2) {
                return Long.valueOf(o2.lastModified()).compareTo(o1.lastModified());
            }                                                                           
        });
        return files;
    }
}
公共类GalleryFragment扩展了片段{
私人回收视图mRecyclerView;
私有文件mGalleryFolder;
私有静态int mColumnCount=3;
私有静态int-mImageWidth;
私有静态图像高度;
公共厨房碎片(){
//必需的空公共构造函数
}
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
视图根视图=充气机。充气(R.layout.fragment\u画廊,容器,假);
mRecyclerView=rootView.findviewbyd(R.id.galleryRecyclerView);
mGalleryFolder=getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES+“/Image Gallery”);
DisplayMetrics DisplayMetrics=新的DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
mImageWidth=displayMetrics.widthPixels/mColumnCount;
mImageHeight=mImageWidth*4/3;
GridLayoutManager layoutManager=新的GridLayoutManager(getActivity(),mColumnCount);
mRecyclerView.setLayoutManager(layoutManager);
文件[]sortedGalleryFolder=sortFilesToLatest(mGalleryFolder);
RecyclerView.Adapter imageAdapter=新的imageAdapter(sortedGalleryFolder、mImageWidth、mImageHeight);
mRecyclerView.setAdapter(imageAdapter);
返回rootView;
}
私有文件[]sortFilesToLatest(文件imageDirectory){
File[]files=imageDirectory.listFiles();
Arrays.sort(文件,新比较器(){
@凌驾
公共整数比较(文件o1、文件o2){
返回Long.valueOf(o2.lastModified()).compareTo(o1.lastModified());
}                                                                           
});
归还文件;
}
}

您可以将第一个片段存储在变量中,然后重复使用它,每次创建第二个片段。比如:

@Override
public Fragment getItem(int i) {
    switch (i) {
        case 0:
            if(photoFragment == null) {
               photoFragment = new PhotoFragment();
            }
            return photoFragment;
        case 1:
            return new GalleryFragment();
        default:
            return null;
    }
}

使用
viewpager.setOffscreenPageLimit(1)


这将设置在空闲状态下应保留在视图层次结构中当前页面一侧的页数。超出此限制的页面将在需要时从适配器重新创建。

将重新创建第一个片段,因为当调用
notifyDataSetChanged()
时,它会影响两个片段,而不仅仅是
i==1
片段

基于您当前状态的解决方案如下

@Override
public int getItemPosition(@NonNull Object object) {
    if (object instanceof PhotoFragment) {
        return POSITION_UNCHANGED;
    }
    return POSITION_NONE;
}

但是,这并不是最优的,因为滚动缓慢,您可以尝试使用子片段来实现您想要的内容

请参见。可能您可以根据对象(我不知道)更改
getItemPosition
。感谢您的回复,但在阅读之后,我不得不承认我仍然不知道如何只重新创建第二个片段,而不是像现在这样重新创建所有片段。我感谢您抽出时间来帮助我。我已经尝试了您的建议,但是在适配器中添加建议的代码并没有改变行为:当我滑动到第二个片段时,我的两个片段仍然会被重新创建,而不仅仅是片段2。抱歉,我可能遗漏了一些明显的内容。请先尝试从您的活动中删除
PageChangedListener
。然后,您可以添加
PhotoFragment
类吗?当我删除
onpagechangeelistener
时,所有片段都不再被重新创建。我已经根据您的请求在我的帖子中添加了PhotoFragment和GalleryFragment类,但是这仍然会导致第一个片段(PhotoFragment)也被重新创建,当第二个片段被重新创建时,当
getItemPosition
OnPageChangeListener
调用时,非常感谢,这解决了我的问题!我同意滚动不是最优的,但我现在可以接受。