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 ,基本上就完成了 ,看一看效果