1,前两天在群里看到有人在讨论土巴兔的选择装修风格的效果,自己也想实现,果断百度一下,有些好的文章,就花了些时间来分析了下,先看看别人土巴兔原装的功能
2,可以看到,基本上可以使用一个vviewpager来实现,主要技术点一下
①android:clipChildren设置为false,意味着不限制子View在其范围内,也就是说子view可以超出父view的范围
②通过PageTransformer来实现缩放动画
③拦截点击事件的位置来实现点击切换viewpager
来看一下代码,首先看一下布局文件main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/page_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:clipChildren="false" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".MainActivity" tools:showIn="@layout/activity_main"> <com.wangjitao.tubatudemo.view.ClipViewPager android:id="@+id/viewPager" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true" android:clipChildren="false" android:overScrollMode="never" /> </RelativeLayout>
其中ClipViewPager是一个自定义的viewpager,主要实现了两个功能,一,判断用户点击事件在不在Viewpager中,二,若在,则设置当前页为其
ClipViewPager.java
package com.wangjitao.tubatudemo.view; import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * Created by wangjitao on 2016/4/15. */ public class ClipViewPager extends ViewPager{ public ClipViewPager(Context context) { super(context); } public ClipViewPager(Context context, AttributeSet attrs) { super(context, attrs); } /** * 重写点击事件,当用户抬起的时候 判断用户点击的区域是否在viewPager的区域中 * 如果是,在判断是在哪个子view上,然后设置当前页为该view * @param ev * @return */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_UP){ View view = viewOfClickOnScreen(ev); if (view != null){ setCurrentItem(indexOfChild(view)); } } return super.dispatchTouchEvent(ev); } private View viewOfClickOnScreen(MotionEvent ev) { int childCount = getChildCount(); int[] location = new int[2]; for (int i = 0; i < childCount; i++) { View v = getChildAt(i); v.getLocationOnScreen(location); int minX = location[0]; int minY = getTop(); int maxX = location[0] + v.getWidth(); int maxY = getBottom(); float x = ev.getX(); float y = ev.getY(); if ((x > minX && x < maxX) && (y > minY && y < maxY)) { return v; } } return null; } }
三,编写自定义的PageTransformer ,来实现当前页切换下一页的控件的缩放问题
ScalePageTransformer.java
package com.wangjitao.tubatudemo.view; import android.os.Build; import android.support.v4.view.ViewPager; import android.view.View; /** * Created by wangjitao on 2016/4/15. */ public class ScalePageTransformer implements ViewPager.PageTransformer { public static final float MAX_SCALE = 1.2f ; public static final float MIN_SCALE = 0.6f ; /** * 当处于最中间的view往左边滑动时,它的position值是小于0的,并且是越来越小,它右边的view的position是从1逐渐减小到0的。 * @param page * @param position */ @Override public void transformPage(View page, float position) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { page.getParent().requestLayout(); } 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); } }
基本上就可以实现了,再贴一下是MainActivity.java和ViewPager的Adapter
MainActivity.java
package com.wangjitao.tubatudemo; import android.content.Context; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.MotionEvent; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.RelativeLayout; import com.wangjitao.tubatudemo.adapter.ClipPagerAdapter; import com.wangjitao.tubatudemo.view.ClipViewPager; import com.wangjitao.tubatudemo.view.ScalePageTransformer; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private Context mContext = MainActivity.this ; private ClipViewPager mViewPager ; private ClipPagerAdapter mClipViewPager ; private List<Integer> mData ; private RelativeLayout mRelativeLayout ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Hi Girl", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); initView(); initData(); } private void initView() { mViewPager = (ClipViewPager) findViewById(R.id.viewPager) ; mViewPager.setPageTransformer(true, new ScalePageTransformer()); mRelativeLayout = (RelativeLayout) findViewById(R.id.page_container); //需要将整个页面的事件分发给ViewPager,不然的话只有ViewPager中间的view能滑动,其他的都不能滑动,这是肯定的, //因为ViewPager总体布局就是中间那一块大小,其他的子布局都跑到ViewPager外面来了 mRelativeLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return mViewPager.dispatchTouchEvent(event); } }); mData = new ArrayList<>(); mClipViewPager = new ClipPagerAdapter(mData,mContext); mViewPager.setAdapter(mClipViewPager); } private void initData() { mData.add(R.mipmap.style_xiandai); mData.add(R.mipmap.style_jianyue); mData.add(R.mipmap.style_oushi); mData.add(R.mipmap.style_zhongshi); mData.add(R.mipmap.style_meishi); mData.add(R.mipmap.style_dzh); mData.add(R.mipmap.style_dny); mData.add(R.mipmap.style_rishi); mViewPager.setOffscreenPageLimit(mData.size()); mClipViewPager.notifyDataSetChanged(); } }
ViewPager的适配器 ClipPagerAdapter.java
package com.wangjitao.tubatudemo.adapter; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import java.util.List; /** * Created by jh on 2016/4/15. */ public class ClipPagerAdapter extends RecyclingPagerAdapter { private List<Integer> mData ; private Context mContext ; public ClipPagerAdapter(List<Integer> mData ,Context mContext ) { this.mData = mData ; this.mContext = mContext ; } @Override public View getView(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(mData.get(position)); return imageView; } @Override public int getCount() { return mData.size(); } }
ok ,基本上就完成了 ,看一看效果