提问人:Elfie 提问时间:11/9/2023 最后编辑:Elfie 更新时间:11/19/2023 访问量:56
向上或向下滑动时,ImageViewer的Viewpager过渡不平滑
Viewpager Transition not smooth for ImageViewer when swiping up or down
问:
我有一个过渡效果,可以从一张图片滑动到下一张图片,然后滑动到上一张图片。滑动的图像在屏幕外移动,上一个/下一个图像从屏幕的另一侧进入。
我无法理解的是,当我向上或向下滑动时,我会得到类似的垂直转换。 我让它工作,但它仍然不顺利。缓慢滑动时,图像会上下跳跃(仅在垂直滑动时)。
ImageViewerActivity(图像查看器活动)
public class ImageViewerActivity extends ActivityBase {
private ArrayList<Uri> mImageUris;
private int mCurrentImageIndex = 0;
private ViewPager mViewPager;
private ImagePagerAdapter mPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_viewer);
initializeUI();
setupToolbar();
mImageUris = getIntent().getParcelableArrayListExtra("image_uris");
mCurrentImageIndex = getIntent().getIntExtra("current_image_index", 0);
mPagerAdapter = new ImagePagerAdapter(this, mImageUris);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(mCurrentImageIndex);
mPagerAdapter.instantiateItem(mViewPager, mCurrentImageIndex);
mPagerAdapter.notifyDataSetChanged();
// Set the PageTransformer to apply the custom animation
mViewPager.setPageTransformer(false, new DepthPageTransformer());
}
private void initializeUI() {
mViewPager = findViewById(R.id.viewPager);
mViewPager.setOnTouchListener(new View.OnTouchListener() {
private float startX = 0;
private float startY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float endX = event.getX();
float endY = event.getY();
float deltaX = Math.abs(endX - startX);
float deltaY = Math.abs(endY - startY);
// Set a threshold value to determine primary direction
float threshold = 200; // Adjust this value as needed
if (deltaX > threshold && deltaX > deltaY) {
// Horizontal swipe
break;
}
// Vertical swipe
float translationY = endY - startY;
v.setTranslationY(translationY);
break;
case MotionEvent.ACTION_UP:
float endYUp = event.getY();
float deltaYUp = endYUp - startY;
// Set a threshold value for vertical swiping
float verticalThreshold = 100; // Adjust this value as needed
// Check if it's a vertical swipe and exceeds a certain threshold
if (deltaYUp < -verticalThreshold) {
// Swipe up, perform dismiss animation
v.animate().translationYBy(-v.getHeight()).withEndAction(new Runnable() {
@Override
public void run() {
onBackPressed();
v.setTranslationY(0); // Reset translation after dismissal
}
});
return true;
} else if (deltaYUp > verticalThreshold) {
// Swipe down, perform dismiss animation
final float translation = endYUp > startY ? v.getHeight() : -v.getHeight();
v.animate().translationYBy(translation).withEndAction(new Runnable() {
@Override
public void run() {
onBackPressed();
v.setTranslationY(0); // Reset translation after dismissal
}
});
return true;
}
// Reset translation on other cases
v.animate().translationY(0);
break;
}
return false;
}
});
}
private void setupToolbar() {
Toolbar toolbar = findViewById(R.id.activity_gallery_view_toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("");
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
DepthPageTransformer(深度页面转换器)
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) {
view.setAlpha(0f);
} else if (position <= 0) {
view.setAlpha(1f);
view.setTranslationX(0f);
view.setScaleX(1f);
view.setScaleY(1f);
} else if (position <= 1) {
view.setAlpha(1 - position);
view.setTranslationX(pageWidth * -position);
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else {
view.setAlpha(0f);
}
}
ImagePager适配器
public class ImagePagerAdapter extends PagerAdapter {
private Context mContext;
private HashMap<Integer, Bitmap> mImages;
private ArrayList<Uri> mImageUris;
private static final String TAG = ImagePagerAdapter.class.getSimpleName();
public ImagePagerAdapter(Context context, ArrayList<Uri> imageUris) {
mContext = context;
mImageUris = imageUris;
Log.d(TAG, "mImageUris: " + mImageUris);
mImages = new HashMap<>(imageUris.size());
if(imageUris.size() > 0) {
notifyDataSetChanged();
}
}
@Override
public int getCount() {
return mImageUris.size();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
//Log.d(TAG, "instantiating position: " + position);
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View itemView = inflater.inflate(R.layout.image_pager_item, container, false);
Glide.with(mContext)
.asBitmap()
.load(mImageUris.get(position))
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
// Add the loaded image to the list
mImages.put(position, resource);
ImageView imageView = itemView.findViewById(R.id.imageView);
imageView.setImageBitmap(mImages.get(position));
container.addView(itemView);
//Log.d(TAG, "added image: " + position);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Handle the case when the resource is cleared (e.g., due to recycling)
//imagesLoaded.getAndIncrement(); // Increment the count in this case
}
});
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
public void updateData(ArrayList<Uri> imageUris) {
mImageUris = imageUris;
notifyDataSetChanged();
}
答:
-1赞
Rob
11/19/2023
#1
我认为您在 Transformation 类中的计算有问题
这是MIN_SCALE可能会弄乱你的整个 cacluculations
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) {
view.setAlpha(0f);
} else if (position <= 0) {
view.setAlpha(1f);
view.setTranslationX(0f);
view.setScaleX(1f);
view.setScaleY(1f);
} else if (position <= 1) {
view.setAlpha(1 - position);
view.setTranslationX(pageWidth * -position);
// actually this is can really make your image jumping
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else {
view.setAlpha(0f);
}
}
尝试使用这个
public class DepthTransformation implements ViewPager.PageTransformer{
@Override
public void transformPage(View page, float position) {
if (position < -1){ // [-Infinity,-1)
// This page is way off-screen to the left.
page.setAlpha(0);
}
else if (position <= 0){ // [-1,0]
page.setAlpha(1);
page.setTranslationX(0);
page.setScaleX(1);
page.setScaleY(1);
}
else if (position <= 1){ // (0,1]
page.setTranslationX(-position*page.getWidth());
page.setAlpha(1-Math.abs(position));
page.setScaleX(1-Math.abs(position));
page.setScaleY(1-Math.abs(position));
}
else { // (1,+Infinity]
// This page is way off-screen to the right.
page.setAlpha(0);
}
}
}
评论
0赞
Elfie
11/21/2023
转换还可以,并且完美无缺。问题出在 onTouch 方法的某个地方,它使垂直滑动成为可能。如果我不将 DepthTransformation 绑定到 imagepager,抖动仍然存在
0赞
Rob
11/21/2023
理解。可能是您正在使用导致抖动的大图像?我还注意到,您仅在加载图像时才添加视图寻呼机的子视图 - 也许您应该在调用图像加载乐趣之前尝试添加它们,然后加载图像 - 对于未加载图像的情况,您可以显示一些占位符(或者可能删除尝试加载图像的子视图?
0赞
Elfie
11/22/2023
图像只有 512x512
0赞
Rob
11/23/2023
尝试在发送图像加载请求之前将视图添加到寻呼机 - 然后请求图像,您创建项目的方式似乎不正常
评论