前段时间开通了自己的私有博客地址韩海龙的博客,我会首先把好的博文发到上面,然后有时间再放到CSDN上面来!

好了,回到正题上来,最近看到有同事在用土巴兔这个app,看了里面的一些效果非常的不错,就试着模仿了一下,首先模仿的是土巴兔里面一个选择装修风格的效果,先看原版效果图如下: 

这种效果实现的方式很多,比如HorizonalScrollView、Recyclerview(水平)、ViewPager等等,这里我使用ViewPager来高仿,为啥通过ViewPager来高仿呢,一是ViewPager提供了PageTransformer,很容易的实现切换动画效果,二是ViewPager很容易控制滑动选中的一项居中,这里先看下高仿后的效果图,效果还是很不错的:

要实现这种效果,核心知识点有如下几个:

  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.ClipViewPagerandroid: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;@Overridepublic 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;@Overrideprotected 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() {@Overridepublic 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() {@Overridepublic 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);//设置OffscreenPageLimitmViewPager.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();}@Overridepublic 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;}@Overridepublic int getCount() {return mList.size();}}
}

这里需要注意几点,一是 mViewPager.setOffscreenPageLimit(list.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);}@Overridepublic 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;}
}

实现原理就是手指点击屏幕,如果点击的位置恰好落在ViewPager某个子View范围内,就让ViewPager切换到哪个子View!viewOfClickOnScreen方法是获取手指点击ViewPager中的哪个子View,最后调用setCurrentItem切换到相应的子View,经过以上设置就大功告成了!

补充一下,RecyclingPagerAdapter是Jake WhartonAndroid大神封装的可用于复用的PagerAdapter。

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

  1. 仿土巴兔装修家居网站(源码+数据库脚本)

    最新江湖家居高仿土巴兔装修门户源码,是一款以江湖家居v6.0至尊版为内核,界面仿土巴兔的装修行业门户源码,功能齐全,单独分站+工长版+代理,分享给大家! 家居门户至尊版专门针对招商加盟打造,无限添加分 ...

  2. 5次折戟IPO,互联网家装这条路,没土巴兔想的那么简单

    土巴兔又一次折戟IPO. 据深交所披露,7月18日土巴兔向深交所提交了撤回创业板IPO的申请,最终深交所决定终止对土巴兔首次公开发行股票并在创业板上市的审核.值得一提的是,这次土巴兔IPO折戟距离它上 ...

  3. 土巴兔被深交所中止审核:营收尚未恢复,流量生意有喜有忧

    近日,贝多财经从深交所创业板了解到,因发行人律师北京市金杜律师事务所因被中国证监会立案调查,土巴兔集团股份有限公司(下称"土巴兔")的上市进程已经处于中止状态,中止时间为2022年 ...

  4. 互联网家装元年,土巴兔能否成为阿里、国美们做家装的风向标?

    "互联网+"概念没能带火的赛道,家装行业应该算一个,不过近期似乎又出现了转机. 千禧年过后,我国房地产蓬勃发展,带动了家装市场从功能性装修到浮夸式装修,再到个性品质化装修方向的不断 ...

  5. 土巴兔CEO王国彬:这五点,决定了你事业的上限

    [编者按]1982年出生的王国彬,至今经历了三次创业,现为国内最大的互联网家装企业土巴兔创始人.2016年3月,王国彬被湖畔大学录取成为第二期学员,成为目前国内互联网行业最受关注的青年领袖之一,以下为 ...

  6. 齐家网、土巴兔、酷家乐,千亿市值路上谁会先圆梦?

    文|熔财经 作者|陈小江 互联网行业易出巨头,但互联网家装是个例外. 作为少数几个拥有万亿市场规模的消费细分赛道之一,家装行业跟汽车.餐饮.休闲食品.家电个等行业不同,属于典型的"大行业小企 ...

  7. 土巴兔上市再折戟,互联网家装没故事

    土巴兔上市又双叒叕暂停了. 在土巴兔创业板IPO审核状态变更为已问询不到半个月的时间,公司保荐人中金公司向深交所提交了关于土巴兔撤回上市的申请,一周后深交所披露了终止土巴兔创业板上市审核的消息. 对此 ...

  8. 祝贺牛辅材品牌获得第七届土巴兔生态大会 “2021年度优秀合作企业”殊荣

    2021年12月21日,第七届土巴兔生态大会在深圳隆重召开.本次活动以"数实融合 产业共创"为主题,土巴兔创始人兼CEO王国彬回顾2021年成绩并发布重磅战略,新的一年将围绕&qu ...

  9. 土巴兔发布2021年战略:创业者引擎赋能,打造品质装企

    时隔一年,12月22日,2020·第六届土巴兔生态大会在深圳隆重举行.发布会上,土巴兔创始人兼CEO王国彬提出了"创业者引擎计划",要为平台生态伙伴提供史上最强力度的扶持政策. 作 ...

最新文章

  1. 百度飞浆行人多目标跟踪笔记
  2. 完整版使用Shell脚本在多个服务器同时实现Mysql建表语句和删除表
  3. 还没掌握Linux文件权限与目录配置命令?就这还不点进来看看干货
  4. Python的scrapy框架POST方式爬虫时碰见__VIEWSTATE和__EVENTVALIDATION的参数处理
  5. 【NOIP】提高组2012 同余方程
  6. Nginx-rtmp直播之业务流程分析--比较详细
  7. java求完数(完全数 完美数)
  8. Dump与Win Program Crash
  9. SyntaxError: (hbase):100: syntax error, unexpected tIDENTIFIER
  10. 11.Excel数据分析-复合型饼图与漏斗图
  11. Teams的MessageExtension最新功能:Initiate actions
  12. 提到这点,人人都不想当产品经理了
  13. PYcharm简单安装教程
  14. Sicily 6271
  15. android的wake_lock介绍
  16. 华为设备好的visio图标及ppt图标
  17. yxy小蒟蒻的201113总结
  18. FreeRTOS学习,适用于FreeRTOS初学者,FreeRTOS整体知识框架
  19. 远程计算机已加入AAD凭据不工作
  20. “钢管舞女孩”之我见

热门文章

  1. Pygame合集】回忆杀-“童年游戏”,看看你中几枪?(附五款源码自取)
  2. 做个it女人不容易呀
  3. 分享一个适合做年终总结软件
  4. Python - matplotlib - 决策曲线分析(Decision Curve Analysis)
  5. Python项目实战(三):爬取东方财富热门股票数据
  6. 基于遗传算法的微电网调度(风、光、蓄电池、微型燃气轮机)(Matlab代码实现)
  7. 决策易医药CRM系统,实现医药代表、公司以及医生三者闭环
  8. AI 人工智能学习之方差分析
  9. 无法在此配置的计算机上运行,win7系统出现“无法将windows配置为在此计算机的硬件上运行”的解决方法...
  10. k1075停运吗_4月16日起,株洲火车站69趟列车调运行时间6对停运