Android开发之利用Viewpager实现图片的预览

1.首先看下效果图

Android常用开源项目(二十五)

运行效果图

2.利用ViewPager图片的预览,类似Gallery的动画效果。下面给出讲解下实现的原理

<1>.原理介绍

它的作用就是让Viewpager展示多个条目,此PageTransformer是为了在Viewpager外面展示图片。

所以PageTransformer并没有改变viewpager的大小状态,我们在viewpager的父控件中拦截dispatchTouchEvent的方法来控制viewpager的滑动和相应点击事件,以此来实现示例中两侧的图片即可点击也可滑动的动画效果。

<2>.具体的代码实现

Android常用开源项目(二十五)

代码结构图

  • grally文件包下的类的实现

GalleryViewPager.java类的实现

public class GalleryViewPager extends ViewPager {

//默认距离

private final static float DISTANCE = 10;

private float downX;

private float downY;

public GalleryViewPager(Context context) {

super(context);

}

public GalleryViewPager(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

if(ev.getAction() == MotionEvent.ACTION_DOWN){

downX = ev.getX();

downY = ev.getY();

}else if (ev.getAction() == MotionEvent.ACTION_UP) {

float upX = ev.getX();

float upY = ev.getY();

//如果 up的位置和down 的位置 距离 > 设置的距离,则事件继续传递,不执行下面的点击切换事件

if(Math.abs(upX - downX) > DISTANCE || Math.abs(upY - downY) > DISTANCE){

return super.dispatchTouchEvent(ev);

}

View view = viewOfClickOnScreen(ev);

if (view != null) {

int index = (Integer) view.getTag();

if (getCurrentItem() != index) {

setCurrentItem(index);

}

}

}

return super.dispatchTouchEvent(ev);

}

/**

* @param ev

* @return

*/

private View viewOfClickOnScreen(MotionEvent ev) {

int childCount = getChildCount();

int currentIndex = getCurrentItem();

int[] location = new int[2];

for (int i = 0; i < childCount; i++) {

View v = getChildAt(i);

int position = (Integer) v.getTag();

v.getLocationOnScreen(location);

int minX = location[0];

int minY = location[1];

int maxX = location[0] + v.getWidth();

int maxY = location[1] + v.getHeight();

if(position < currentIndex){

maxX -= v.getWidth() * (1 - ScalePageTransformer.MIN_SCALE) * 0.5 + v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;

minX -= v.getWidth() * (1 - ScalePageTransformer.MIN_SCALE) * 0.5 + v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;

}else if(position == currentIndex){

minX += v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE));

}else if(position > currentIndex){

maxX -= v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;

minX -= v.getWidth() * (Math.abs(1 - ScalePageTransformer.MAX_SCALE)) * 0.5;

}

float x = ev.getRawX();

float y = ev.getRawY();

if ((x > minX && x < maxX) && (y > minY && y < maxY)) {

return v;

}

}

return null;

}

}

ScalePageTransformer.java类的实现

public class ScalePageTransformer implements ViewPager.PageTransformer {

public static final float MAX_SCALE = 1.2f;

public static final float MIN_SCALE = 0.6f;

@Override

public void transformPage(View page, float position) {

if (position < -1) {

position = -1;

} else if (position > 1) {

position = 1;

}

float tempScale = position < 0 ? 1 + position : 1 - position;

float slope = (MAX_SCALE - MIN_SCALE) / 1;

//一个公式

float scaleValue = MIN_SCALE + tempScale * slope;

page.setScaleX(scaleValue);

page.setScaleY(scaleValue);

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {

page.getParent().requestLayout();

}

}

}

  • adapter文件包下类的代码实现

AdapterBean.java类的代码实现

public class AdapterBean {

private View[] activeViews = new View[0];

private int[] activeViewTypes = new int[0];

private SparseArray<View>[] scrapViews;

private int viewTypeCount;

private SparseArray<View> currentScrapViews;

public void setViewTypeCount(int viewTypeCount) {

if (viewTypeCount < 1) {

return;

}

//noinspection unchecked

SparseArray<View>[] scrapViews = new SparseArray[viewTypeCount];

for (int i = 0; i < viewTypeCount; i++) {

scrapViews[i] = new SparseArray<View>();

}

this.viewTypeCount = viewTypeCount;

currentScrapViews = scrapViews[0];

this.scrapViews = scrapViews;

}

protected boolean shouldRecycleViewType(int viewType) {

return viewType >= 0;

}

View getScrapView(int position, int viewType) {

if (viewTypeCount == 1) {

return retrieveFromScrap(currentScrapViews, position);

} else if (viewType >= 0 && viewType < scrapViews.length) {

return retrieveFromScrap(scrapViews[viewType], position);

}

return null;

}

void addScrapView(View scrap, int position, int viewType) {

if (viewTypeCount == 1) {

currentScrapViews.put(position, scrap);

} else {

scrapViews[viewType].put(position, scrap);

}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

scrap.setAccessibilityDelegate(null);

}

}

void scrapActiveViews() {

final View[] activeViews = this.activeViews;

final int[] activeViewTypes = this.activeViewTypes;

final boolean multipleScraps = viewTypeCount > 1;

SparseArray<View> scrapViews = currentScrapViews;

final int count = activeViews.length;

for (int i = count - 1; i >= 0; i--) {

final View victim = activeViews[i];

if (victim != null) {

int whichScrap = activeViewTypes[i];

activeViews[i] = null;

activeViewTypes[i] = -1;

if (!shouldRecycleViewType(whichScrap)) {

continue;

}

if (multipleScraps) {

scrapViews = this.scrapViews[whichScrap];

}

scrapViews.put(i, victim);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

victim.setAccessibilityDelegate(null);

}

}

}

pruneScrapViews();

}

/**

* Makes sure that the size of scrapViews does not exceed the size of activeViews.

* (This can happen if an adapter does not recycle its views).

*/

private void pruneScrapViews() {

final int maxViews = activeViews.length;

final int viewTypeCount = this.viewTypeCount;

final SparseArray<View>[] scrapViews = this.scrapViews;

for (int i = 0; i < viewTypeCount; ++i) {

final SparseArray<View> scrapPile = scrapViews[i];

int size = scrapPile.size();

final int extras = size - maxViews;

size--;

for (int j = 0; j < extras; j++) {

scrapPile.remove(scrapPile.keyAt(size--));

}

}

}

static View retrieveFromScrap(SparseArray<View> scrapViews, int position) {

int size = scrapViews.size();

if (size > 0) {

// See if we still have a view for this position.

for (int i = 0; i < size; i++) {

int fromPosition = scrapViews.keyAt(i);

View view = scrapViews.get(fromPosition);

if (fromPosition == position) {

scrapViews.remove(fromPosition);

return view;

}

}

int index = size - 1;

View r = scrapViews.valueAt(index);

scrapViews.remove(scrapViews.keyAt(index));

return r;

} else {

return null;

}

}

}

MyPageradapter.java类的代码实现

public abstract class MyPageradapter extends PagerAdapter {

static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;

private final AdapterBean AdapterBean;

public MyPageradapter() {

this(new AdapterBean());

}

MyPageradapter(AdapterBean AdapterBean) {

this.AdapterBean = AdapterBean;

AdapterBean.setViewTypeCount(getViewTypeCount());

}

@Override

public void notifyDataSetChanged() {

AdapterBean.scrapActiveViews();

super.notifyDataSetChanged();

}

@Override

public final Object instantiateItem(final ViewGroup container, final int position) {

int viewType = getItemViewType(position);

View view = null;

if (viewType != IGNORE_ITEM_VIEW_TYPE) {

view = AdapterBean.getScrapView(position, viewType);

}

view = getView(position, view, container);

container.addView(view);

return view;

}

@Override

public final void destroyItem(ViewGroup container, int position, Object object) {

View view = (View) object;

container.removeView(view);

int viewType = getItemViewType(position);

if (viewType != IGNORE_ITEM_VIEW_TYPE) {

AdapterBean.addScrapView(view, position, viewType);

}

}

@Override

public final boolean isViewFromObject(View view, Object object) {

return view == object;

}

public int getViewTypeCount() {

return 1;

}

@SuppressWarnings("UnusedParameters") // Argument potentially used by subclasses.

public int getItemViewType(int position) {

return 0;

}

public abstract View getView(int position, View convertView, ViewGroup container);

}

  • 以上是实现图片滑动的一些必须文件,下面给出Activity类,在此类中可以实现页面视觉的效果

public class MainActivity extends AppCompatActivity {

private GalleryViewPager mViewPager;

private SimpleAdapter mPagerAdapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mViewPager = (GalleryViewPager) findViewById(R.id.viewpager);

mViewPager.setPageTransformer(true, new ScalePageTransformer());

findViewById(R.id.root).setOnTouchListener(new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

return mViewPager.dispatchTouchEvent(event);

}

});

mPagerAdapter = new SimpleAdapter(this);

mViewPager.setAdapter(mPagerAdapter);

initData();

}

private void initData() {

List<Integer> list = new ArrayList<>();

list.add(R.drawable.wo);

list.add(R.drawable.wo1);

list.add(R.drawable.wo2);

list.add(R.drawable.wo3);

list.add(R.drawable.wo4);

list.add(R.drawable.wo5);

list.add(R.drawable.wo);

list.add(R.drawable.wo1);

//设置OffscreenPageLimit

mViewPager.setOffscreenPageLimit(Math.min(list.size(), 5));

mPagerAdapter.addAll(list);

}

public class SimpleAdapter extends MyPageradapter {

private final List<Integer> mList;

private final Context mContext;

public SimpleAdapter(Context context) {

mList = new ArrayList<>();

mContext = context;

}

public void addAll(List<Integer> list) {

mList.addAll(list);

notifyDataSetChanged();

}

@Override

public View getView(final int position, View convertView, ViewGroup container) {

ImageView imageView = null;

if (convertView == null) {

imageView = new ImageView(mContext);

} else {

imageView = (ImageView) convertView;

}

imageView.setTag(position);

imageView.setImageResource(mList.get(position));

imageView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

if ((mViewPager.getCurrentItem() ) == position) {

Toast.makeText(mContext, "点击的位置是:::"+position, Toast.LENGTH_SHORT).show();

}

}

});

return imageView;

}

@Override

public int getCount() {

return mList.size();

}

}

}

  • 下面给出实现的一些资源文件

首先是drawable文件夹下的资源文件,此文件夹下给出一些图片资源(备注:如果需要网络图片资源,可以通过网络地址下载图片,在此grally中显示图片滑动效果)。在此不在给出这些图片了。

其次,需要在layout文件夹下给出布局文件activity_main.xml布局文件。

Android常用开源项目(二十五)

activity_main.xml布局文件

最后,以上是viewpager中实现图片滑动的一个简单的demo,有不足的地方希望大家指正批评

相关文章:

  • 2021-07-09
  • 2021-10-24
  • 2021-11-28
  • 2021-07-11
  • 2022-01-04
  • 2021-12-29
  • 2021-10-21
  • 2021-06-13
猜你喜欢
  • 2021-07-05
  • 2021-08-15
  • 2022-01-20
  • 2021-09-08
  • 2021-06-27
  • 2021-10-01
  • 2021-08-05
相关资源
相似解决方案