向上或向下滑动时,Viewpager 的 ImageViewer 过渡不平滑

问题描述 投票:0回答:1

我有一个过渡效果,可以从一张图像滑动到下一张图像,再滑动到上一张图像。滑动的图像被移动到屏幕之外,上一个/下一个图像从屏幕的另一侧进入。

我无法实现的是,当我向上或向下滑动时,我会得到类似的垂直变换。 我已经开始工作了,但仍然不顺利。缓慢滑动时图像会有点上下跳动(仅在垂直滑动时)。

图像查看器活动

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);
    }
}

深度页面转换器

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);
    }
}

ImagePagerAdapter

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();
}
android android-viewpager imageview android-adapter android-transitions
1个回答
0
投票

我认为你在转换课上的计算有问题

这里是 MIN_SCALE,它可能会弄乱你的整个计算

    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);

    }
}

}

© www.soinside.com 2019 - 2024. All rights reserved.