您的位置:首页 > 移动开发 > Android开发

Android 自定义viewpager 三张图片在同一屏幕轮播的效果

2017-08-15 17:04 696 查看
github:https://github.com/nickeyCode/RoundImageViewPager

说实话不知道怎么描述这个效果,在网页上见得跟多,公司要求做这个效果得时候不知道怎么用文字描述找不到对应的dome只好自己写。

先上图



大概效果就是这个。主要用的的知识点就是viewpager的自定义动画。

项目目录:



roundimg是圆形图片,继承ImageView的,上网好多可以搜索得到

viewpager主要分成三部分

一是viewpager本身,设置adapter,绑定监听器等。

二是adapter,继承PagerAdapter,用法跟listview的差不多。

三是动画类,继承PageTransformer。

首先看看最核心的动画类(能做到这个效果就是根据对应的动画变动)

HeadViewPagerTransformer.Java

public class HeadViewPagerTransformer implements PageTransformer{
private static final float MIN_SCALE = 0.75f;
//主要是设置在不同位置上的VIEW的活动动画
@Override
public void transformPage(View view, float position) {
// TODO Auto-generated method stub
int pageWidth = view.getWidth();

if (position < -1) { // [-Infinity,-1)
view.setAlpha(0);
}
else if (position <= 0) { // [-1,0]
view.setAlpha(1);
view.setTranslationX(0);
float x = -1.0f * (2f / 3f) * pageWidth * position;
view.setTranslationX(x);
float scaleFactor = MIN_SCALE + (2 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else if (position <= 1) { // (0,1]
view.setAlpha(1);
float x = -1.0f * (2f / 3f) * pageWidth * position;
view.setTranslationX(x);
float scaleFactor = MIN_SCALE + (2 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);

}
}

}


因为在这个类中,viewpager中view都有对应的位置编号,在正中间显示的view位置是0

在左边的view位置是-1,在右边的view位置是1.(相当于一个坐标轴)

只要viewpager发生滑动,就会调用tansFromPager();position之说以是float类型,是因为如果发生滑动,位置就会有对应的变化,而变化精确到0.0001.

在函数中使用if-else来设定在不同位置区间中的view的动画变化;

if (position < -1) { // [-Infinity,-1)
view.setAlpha(0);
}


这是负无穷到-1的区间,当然,如果你的viewpager缓存的view只有三个的话,这个就没有作用了,因为最多只有三个view,多出来就销毁了。

else if (position <= 0) { // [-1,0]
view.setAlpha(1);
view.setTranslationX(0);
float x = -1.0f * (2f / 3f) * pageWidth * position;
view.setTranslationX(x);
float scaleFactor = MIN_SCALE + (2 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor); }


这是-1到0的区间,就是左边的view到中间或中间的view到左边的动画效果,这里主要是做了两个动画变化,一是大小,二是位置。

这两个变化公式是根据位置的变化与动画数值的关系,解二元一次方程求出来的(初中数学知识。。。。)

具体方式就是balbalblabalbalb。。。。。(不多说)

同理

else if (position <= 1) { // (0,1]
view.setAlpha(1);
float x = -1.0f * (2f / 3f) * pageWidth * position;
view.setTranslationX(x);
float scaleFactor = MIN_SCALE + (2 - MIN_SCALE) * (1 - Math.abs(position));  }


0到1的区间一样。在实际动画设计的过程中,公式是需要变动的。

剩下的都是普通的viewpager使用,设置adapter (HeadViewPagerAdapter.java)

public class HeadViewPagerAdapter extends PagerAdapter {

private Context mContext;
private List<MyImageView> mList;

public HeadViewPagerAdapter(Context context,List<MyImageView> list){
this.mContext = context;
this.mList = list;
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return mList.size();
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == arg1;
}
//当缓存view的数量超过上限时,会销毁最先的一个
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
//Log.d("remove", mImageViews[position].hashCode() + "");
container.removeView(mList.get(position));
}
//添加View
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
container.addView(mList.get(position),0);
return mList.get(position);
}

}


还有就是对应的绑定:HeadViewPager.java

public class HeadViewPager extends FrameLayout {

private Context mContext;
private ViewPager mViewPager;
private List<Integer> mImageIds;
private List<MyImageView> mImageViews;
private ViewGroup mViewGroup;
private List<ImageView> tips;
private int tipsChoseImgId;
private int tipsUnchoseImgId;

public HeadViewPager(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
creatView(context);
}

public HeadViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
creatView(context);
}

public HeadViewPager(Context context) {
super(context);
// TODO Auto-generated constructor stub
creatView(context);
}

public HeadViewPager(Context context,List<MyImageView> imgageList) {
super(context);
// TODO Auto-generated constructor stub
creatView(context,imgageList);
}

public void creatView(Context context){
this.mContext = context;
LayoutInflater.from(context).inflate(R.layout.head_view_pager, this);
mViewPager = (ViewPager)findViewById(R.id.viewpager);
mViewGroup = (ViewGroup)findViewById(R.id.viewgroup);
mImageViews = new ArrayList<MyImageView>();
mImageIds = new ArrayList<Integer>();
tips = new ArrayList<ImageView>();
tipsChoseImgId = R.drawable.img_bg_chose;
tipsUnchoseImgId = R.drawable.img_bg_unchose;
build();
}

public void creatView(Context context,List<MyImageView> imgageList){
this.mContext = context;
LayoutInflater.from(context).inflate(R.layout.head_view_pager, this);
mViewPager = (ViewPager)findViewById(R.id.viewpager);
mViewGroup = (ViewGroup)findViewById(R.id.viewgroup);
mImageViews = imgageList;
mImageIds = new ArrayList<Integer>();
tips = new ArrayList<ImageView>();
tipsChoseImgId = R.drawable.img_bg_chose;
tipsUnchoseImgId = R.drawable.img_bg_unchose;
build();
}

public void build(){
buildTips();
mViewPager.setAdapter(new HeadViewPagerAdapter(mContext,mImageViews));
//设置默认显示页面为第0页
mViewPager.setCurrentItem(0);
//设置选择页面时的动画
mViewPager.setPageTransformer(true, new HeadViewPagerTransformer());
//设置缓存View的个数,默认是3个,这表示缓存了5个
mViewPager.setOffscreenPageLimit(4);
//页面发生改变的监听器
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
//选择发生改变
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
changeTips(arg0);
}
//有滑动操作
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub

}
//滑动操作或选择改变
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub

}
});

}
//初始化底部导航圆点条
public void buildTips(){
for (int i = 0 ; i < mImageViews.size() ; i ++){
ImageView imageView = new ImageView(mContext);
imageView.setLayoutParams(new LayoutParams(10,10));
if(i == 0){
imageView.setBackgroundResource(tipsChoseImgId);
}else{
imageView.setBackgroundResource(tipsUnchoseImgId);
}
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(12,12));
layoutParams.leftMargin = 5;
layoutParams.rightMargin = 5;
tips.add(imageView);
mViewGroup.addView(imageView, layoutParams);
}
}
//当选定的页面发生改变时,导航条也对应改变
public void changeTips(int index){
for (int i = 0 ; i < tips.size() ; i ++){
if(i == index){
tips.get(i).setBackgroundResource(tipsChoseImgId);
}else{
tips.get(i).setBackgroundResource(tipsUnchoseImgId);
}
}
}

public Context getmContext() {
return mContext;
}

public void setmContext(Context mContext) {
this.mContext = mContext;
}

public ViewPager getmViewPager() {
return mViewPager;
}

public void setmViewPager(ViewPager mViewPager) {
this.mViewPager = mViewPager;
}

public List<MyImageView> getmImageViews() {
return mImageViews;
}
//改变图片队列时,要更新整个viewPager
public void setmImageViews(List<MyImageView> mImageViews) {
this.mImageViews = mImageViews;
this.mViewPager.notify();
this.mViewPager.setCurrentItem(0);

}

public ViewGroup getmViewGroup() {
return mViewGroup;
}

public void setmViewGroup(ViewGroup mViewGroup) {
this.mViewGroup = mViewGroup;
}

public int getTipsChoseImgId() {
return tipsChoseImgId;
}

public void setTipsChoseImgId(int tipsChoseImgId) {
this.tipsChoseImgId = tipsChoseImgId;
}

public int getTipsUnchoseImgId() {
return tipsUnchoseImgId;
}

public void setTipsUnchoseImgId(int tipsUnchoseImgId) {
this.tipsUnchoseImgId = tipsUnchoseImgId;
}
}


样例项目资源:
http://download.csdn href="http://lib.csdn.net/base/dotnet" target=_blank>.NET/detail/nickey_1314/8932807

点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: