Android-通过自定义ViewPager来高仿土巴兔选择装修风格效果(中间放大效果)

Ç°¶Îʱ¼ä¿ªÍ¨ÁË×Ô¼ºµÄ˽Óв©¿ÍµØÖ·º«º£ÁúµÄ²©¿Í£¬ÎÒ»áÊ×ÏȰѺõIJ©ÎÄ·¢µ½ÉÏÃ棬ȻºóÓÐʱ¼äÔٷŵ½ÉÏÃæÀ´£¡

ºÃÁË£¬»Øµ½ÕýÌâÉÏÀ´£¬×î½ü¿´µ½ÓÐͬÊÂÔÚÓÃÍÁ°ÍÍÃÕâ¸öapp£¬¿´ÁËÀïÃæµÄһЩЧ¹û·Ç³£µÄ²»´í£¬¾ÍÊÔ×ÅÄ£·ÂÁËһϣ¬Ê×ÏÈÄ£·ÂµÄÊÇÍÁ°ÍÍÃÀïÃæÒ»¸öÑ¡Ôñ×°ÐÞ·ç¸ñµÄЧ¹û£¬ÏÈ¿´Ô­°æЧ¹ûͼÈçÏ£º 

20150928093046209.gif

ÕâÖÖЧ¹ûʵÏֵķ½Ê½ºÜ¶à£¬±ÈÈçHorizonalScrollView¡¢Recyclerview(ˮƽ)¡¢ViewPagerµÈµÈ£¬ÕâÀïÎÒʹÓÃViewPagerÀ´¸ß·Â£¬ÎªÉ¶Í¨¹ýViewPagerÀ´¸ß·ÂÄØ£¬Ò»ÊÇViewPagerÌṩÁËPageTransformer£¬ºÜÈÝÒ×µÄʵÏÖÇ뻶¯»­Ð§¹û£¬¶þÊÇViewPagerºÜÈÝÒ׿ØÖÆ»¬¶¯Ñ¡ÖеÄÒ»Ïî¾ÓÖУ¬ÕâÀïÏÈ¿´Ï¸߷ºóµÄЧ¹ûͼ£¬Ð§¹û»¹ÊǺܲ»´íµÄ£º

20150928093108444.gif

ҪʵÏÖÕâÖÖЧ¹û£¬ºËÐÄ֪ʶµãÓÐÈçϼ¸¸ö£º

  1. android:clipChildrenÉèÖÃΪfalse£¬Òâζ×Ų»ÏÞÖÆ×ÓViewÔÚÆ䷶ΧÄÚ£¬Ò²¾ÍÊÇ˵×Óview¿ÉÒÔ³¬³ö¸¸viewµÄ·¶Î§

  2. ͨ¹ýPageTransformerÀ´ÊµÏÖËõ·Å¶¯»­

  3. À¹½Øµã»÷ʼþµÄλÖÃÀ´ÊµÏÖµã»÷Çл»viewpager£¬Õâ¸öΪʲôҪʵÏÖ£¬ºóÃæÔÙ˵


ÏÂÃæÎÒÃÇÒ»²½Ò»²½½²½âÀ´ÊµÏÖÕâ¸ö²¼¾ÖЧ¹û

¶¨Òå²¼¾Ö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.hhl.tubatu.ClipViewPager
        android:id="@+id/viewpager"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:clipChildren="false"
        android:overScrollMode="never" />
</RelativeLayout>

ÉÏÃæµÄRelativeLayoutºÍ×Ô¶¨ÒåµÄClipViewPager¶¼¸÷×ÔÌí¼ÓÁËÒ»¸öÊôÐÔandroid:clipChildren=¡±false¡±£¬clipChildrenµÄÒâ˼ÊÇÊÇ·ñÏÞÖÆ×ÓViewÔÚÆ䷶ΧÄÚ£¬Õâ¸öĬÈÏÊÇtrue£¬Ò²¾ÍÊÇĬÈÏÊÇÏÞÖÆ×ÓviewÔÚÆ䷶ΧµÄ

¸øViewPagerÉèÖÃËõ·Å¶¯»­£¬ÕâÀïͨ¹ýPageTransformerÀ´ÊµÏÖ

mViewPager = (ClipViewPager) findViewById(R.id.viewpager);
mViewPager.setPageTransformer(true, new ScalePageTransformer());

ÔÙÀ´¿´ScalePageTransformerµÄʵÏÖ£¬ºËÐľÍÊÇʵÏÖtransformPage(View page, float position)Õâ¸ö·½·¨

/**
 * Created by HanHailong on 15/9/27.
 */
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);
    }
}

ÆäʵºËÐÄ´úÂë¾ÍÊÇÕâ¸ö¶¯»­ÊµÏÖ²¿·Ö£¬ÕâÀïÉèÖÃÁËÒ»¸ö×î´óËõ·ÅºÍ×îСËõ·Å±ÈÀý£¬µ±´¦ÓÚ×îÖмäµÄviewÍù×ó±ß»¬¶¯Ê±£¬ËüµÄpositionÖµÊÇСÓÚ0µÄ£¬²¢ÇÒÊÇÔ½À´Ô½Ð¡,ËüÓұߵÄviewµÄpositionÊÇ´Ó1Öð½¥¼õСµ½0µÄ¡£

ÏÂÃæÎÒÃÇ¿´ÏÂÔÚActivityµÄÍêÕûʵÏÖ´úÂë

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.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.hhl.tubatu.adapter.RecyclingPagerAdapter;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    private ClipViewPager mViewPager;
    private TubatuAdapter mPagerAdapter;
    @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, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        mViewPager = (ClipViewPager) findViewById(R.id.viewpager);
        mViewPager.setPageTransformer(true, new ScalePageTransformer());
        findViewById(R.id.page_container).setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mViewPager.dispatchTouchEvent(event);
            }
        });
        mPagerAdapter = new TubatuAdapter(this);
        mViewPager.setAdapter(mPagerAdapter);
        initData();
    }
    private void initData() {
        List<Integer> list = new ArrayList<>();
        list.add(R.drawable.style_xiandai);
        list.add(R.drawable.style_jianyue);
        list.add(R.drawable.style_oushi);
        list.add(R.drawable.style_zhongshi);
        list.add(R.drawable.style_meishi);
        list.add(R.drawable.style_dzh);
        list.add(R.drawable.style_dny);
        list.add(R.drawable.style_rishi);
        //ÉèÖÃOffscreenPageLimit
        mViewPager.setOffscreenPageLimit(list.size());
        mPagerAdapter.addAll(list);
    }
    public static class TubatuAdapter extends RecyclingPagerAdapter {
        private final List<Integer> mList;
        private final Context mContext;
        public TubatuAdapter(Context context) {
            mList = new ArrayList<>();
            mContext = context;
        }
        public void addAll(List<Integer> list) {
            mList.addAll(list);
            notifyDataSetChanged();
        }
        @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(mList.get(position));
            return imageView;
        }
        @Override
        public int getCount() {
            return mList.size();
        }
    }
}

ÕâÀïÐèÒª½«setOffscreenPageLimitµÄÖµÉèÖóÉÊý¾ÝÔ´µÄ×ܸöÊý£¬Èç¹û²»¼ÓÕâ¾ä»°£¬»áµ¼ÖÂ×óÓÒÇл»Òì³££»¶þÊÇÐèÒª½«Õû¸öÒ³ÃæµÄʼþ·Ö·¢¸øViewPager£¬²»È»µÄ»°Ö»ÓÐViewPagerÖмäµÄviewÄÜ»¬¶¯£¬ÆäËûµÄ¶¼²»ÄÜ»¬¶¯£¬ÕâÊǿ϶¨µÄ£¬ÒòΪViewPager×ÜÌå²¼¾Ö¾ÍÊÇÖмäÄÇÒ»¿é´óС£¬ÆäËûµÄ×Ó²¼¾Ö¶¼Åܵ½ViewPagerÍâÃæÀ´ÁË¡£ÈýÊÇÄã·¢ÏÖViewPager¼ÓÁËsetOnTouchListener·½·¨ºó£¬»¬¶¯ÊÇ¿ÉÒÔÁË£¬µ«Êǵã»÷×óÓÒÁ½±ß²»ÄÜÇл»£¬ÕâÀïÐèÒªÖØдViewPagerµÄdispatchTouchEvent·½·¨£¬ÏÂÃæ¿´ClipViewPager´úÂ룺

package com.hhl.tubatu;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
 * Created by HanHailong on 15/9/27.
 */
public class ClipViewPager extends ViewPager {
    public ClipViewPager(Context context) {
        super(context);
    }
    public ClipViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @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);
    }
    /**
     * @param ev
     * @return
     */
    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;
    }
}

ʵÏÖÔ­Àí¾ÍÊÇÊÖÖ¸µã»÷ÆÁÄ»£¬Èç¹ûµã»÷µÄλÖÃÇ¡ºÃÂäÔÚViewPagerij¸ö×ÓView·¶Î§ÄÚ£¬¾ÍÈÃViewPagerÇл»µ½Äĸö×ÓView£¡viewOfClickOnScreen·½·¨ÊÇ»ñÈ¡ÊÖÖ¸µã»÷ViewPagerÖеÄÄĸö×ÓView£¬×îºóµ÷ÓÃsetCurrentItemÇл»µ½ÏàÓ¦µÄ×ÓView£¬¾­¹ýÒÔÉÏÉèÖþʹ󹦸æ³ÉÁË£¡

²¹³äһϣ¬RecyclingPagerAdapterÊÇJake WhartonAndroid´óÉñ·â×°µÄ¿ÉÓÃÓÚ¸´ÓõÄPagerAdapter¡£

×îºó¸½ÉÏÔ´Âëgithub