我将ViewPager与两个片段一起使用:PhotoFragment和GalleryFragment。
如果我滑动到第二个片段(GalleryFragment),我总是想重新创建该片段。
但是,当我滑动回到第一个片段(PhotoFragment)时,我希望将其从内存中拉出。
我尝试针对此问题Update ViewPager dynamically?实施解决方案
我利用notifyDataSetChanged()
并覆盖了getItemPosition()
以便在滑动到第二个片段时返回POSITION_NONE。
当我滑动到第二个片段时,它会正确地重新创建。但是,当我滑动回到第一个片段时,我注意到它也已被重新创建。
我猜想返回POSITION_NONE会导致适配器中所有片段的删除和重新创建。我是Android初学者,不知道如何仅重新创建第二个片段。
使用ViewPager的MainActivity:
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);
}
}
GalleryFragment:
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;
}
}
最佳答案
重新创建第一个片段是因为当您调用notifyDataSetChanged()
时,它会影响两个片段,不仅会影响i == 1
片段
基于您当前状态的解决方案是这样的
@Override
public int getItemPosition(@NonNull Object object) {
if (object instanceof PhotoFragment) {
return POSITION_UNCHANGED;
}
return POSITION_NONE;
}
但是,这并不是最佳选择,因为滚动很慢,您可以尝试使用子片段来实现所需的功能
关于android - Android ViewPager:重新创建单个特定 fragment ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56430922/