- 浏览: 128930 次
- 性别:
- 来自: 北京
最新评论
-
qiuhuahui1:
真的有用,帮我节省了大把的时间。
android的ant编译打包 -
fxiaozj:
楼主,有没有demo?
Android ViewGroup实现页面滑动效果并实现不同的动画效果 -
sgjsdf5944:
你好,请问下楼主如果我想在安装完成页面上控制打开不可用该怎么实 ...
Android 监控程序安装和删除的实现 -
renfujiang:
养成好习惯,看过别人的文章 就得评论 增加点人气 好文章 我是 ...
android的ant编译打包 -
leishengwei:
你好,第一种方法在4.0时,输入法是弹不出去了,但是光标不能正 ...
Android如何关闭EditText中的软键盘
这应该是自己第一次开始写博客,今天起想要记录下自己工作上学到的一些东西,除了能随时查看自己的曾经学到的东西,也可以跟大家分享一下自己的一些经验。由于自己刚到3g门户去实习,其实有很多技术上东西都不是很懂,也只能慢慢去学了。一进来的实习,带我的那位辅导员就让我实现像Launcher那样的滑动,并且实现滑动过程中的效果~~~这下惨了,自己最薄弱的一环,对一些界面上的东西都很少去碰,只能乖乖的去网上搜搜资料恶补一下了。
不扯那么多了,直接进入正题吧,其实实现像Launcher那样的滑动效果有几种方法,不过我在这里用继承ViewGroup的方法去实现。要是实现ViewGroup必须重写onLayout()和onMeasure()这两个方法,这个两个方法在创建的时候会自动调用,调用的顺序是onMeasure()-->onLayout()。
onMeasure()方法中是存储在ViewGroup里面每个子View的默认宽度和高度,以下代码就是把每个子View的默认宽度和高度都设置与父类的一样。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("onMeasure", "onMeasure----------");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec); //转换宽度
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");
}
// 将所有的子View高度和宽度都定义成和父View一样
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
//滑动到默认屏幕
scrollTo(mCurScreen * width, 0);
}
而onLayout()就是设置每个子View在屏幕那个位置来显示出子View,现在在OnLayout()方法里面设置是从左到右横向绘出每个子View,其中onLayout这个方法的实现是在什么地方显示子view,显示的范围是多大,这个方法不能改变每个view原本的大小的
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("onLayout", "onLayout----------");
if(mTouchState == TOUCH_STATE_REST){
int childLeft = 0;//从坐标0开始绘画
final int childCount = getChildCount();
for (int i=0; i<childCount; i++) {
final View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
final int childWidth = childView.getMeasuredWidth();
//根据left , top ,right,bottom 四个参数,调用子View的layout()方法将其放置在父类中,参照物是父View
childView.layout(childLeft, 0,
childLeft+childWidth, childView.getMeasuredHeight());
childLeft += childWidth;
}
}
}
}
onMeasure和onLayout这个两个方法只是设置子View大小和绘画位置,真正把每个子View绘画出来是在onDispathDraw()方法里(一开始我还以为在onDraw,但是ViewGroup那里是不会调用onDraw方法)实现的,要是实现子view滑动时候的效果就可以再这里实现。
到了这里就把整个页面里的子view都画出来,要实现滑动的效果就需要在onTouchEvent那里做功夫,主要实现滑动动作是在MotionEvent.Action_Move里的scrollBy(x,y),x表示水平滑动的距离,y表示垂直滑动的距离,因为这里只水平方向的滑动,所以y可以设置为0。
如果要像一些桌面应用那样,当手松开后就滑动到某个完整的view的页面,这就需要用Scroller和在MotionEvent.Action_Up上设置,Scroller是可以控制整个页面的滑动,而在MotionEvent.Action_Up上面时判断手指滑动的速度,可以自己定义一个速度的基准,当达到就跨屏滑动,没有达到就判断滑动的位置是否超过当前屏幕的一半,超过就跨屏,否则仍然恢复到当前屏幕,具体还有一些数值需要自己去计算定义自己喜欢效果。代码如下:
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//获得动作捕捉器
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);//开始捕捉动作
final int action = event.getAction();
final float x = event.getX();
final float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()){
mScroller.abortAnimation();
}
mLastMotionX = x;
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int)(mLastMotionX - x);
mLastMotionX = x;
scrollBy(deltaX, 0);
break;
case MotionEvent.ACTION_UP://放手后的动作
final VelocityTracker velocityTracker = mVelocityTracker;
//计算滑动速度,参数1000表示以1000毫秒为单位计算,即以秒为单位
velocityTracker.computeCurrentVelocity(1000);
int velocityX = (int) velocityTracker.getXVelocity();
//如果向左或者向右的滑动速度超过了基础线,则直接切换屏幕;如果没有,则判断滑动的距离是否超过了屏幕一半的距离,也就是View的一半Width
if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {
// Fling enough to move left
snapToScreen(mCurScreen - 1);
} else if (velocityX < -SNAP_VELOCITY
&& mCurScreen < getChildCount() - 1) {
// Fling enough to move right
snapToScreen(mCurScreen + 1);
} else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
mTouchState = TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
break;
}
return true;
}
public void snapToDestination() {
final int screenWidth = getWidth();
final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;
snapToScreen(destScreen);
}
public void snapToScreen(int whichScreen) {
// get the valid layout page
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));
if (getScrollX() != (whichScreen*getWidth())) {
final int delta = whichScreen*getWidth()-getScrollX();
mScroller.startScroll(getScrollX(), 0,
delta, 0, Math.abs(delta)*2);
mCurScreen = whichScreen;
invalidate(); // Redraw the layout
}
}
现在基本算是实现了整个屏幕滑动的效果,要实现滑动的动画就必须要在dispathDraw(Canvas canvas)的canvas来实现了,在ViewGroup里面有一个方法drawChild(),通过这个将每个view都重绘上去,其中的变换不外乎translate,scale这个几种,当然要实现其他比较复杂的效果就需要其他操作了,所以现在要重写dispatchDraw里面的方法,而我现在要实现像Go桌面那样的弹跳效果,这里是通过获取屏幕的左位置和每个子view的左坐标来进行绘画,因为子view的位置是固定的,而屏幕的左坐标却在不断的变化。在这里是用一个判断为基准,就是每个子view的左坐标与屏幕左坐标的距离是否超过一个子view的宽度,超过距离的子view将不做变换。
int dx=Math.abs(getScrollX()-view.getLeft())通过这个获取每个子view的左坐标和屏幕左坐标的距离,这里我是实现弹跳的效果,其实只是对子view的y轴上的位置进行变换,用dx/view.getWidth()来获取滑动距离的比例,通过canvas.translate(0.0f, -(1.0f*dx/view.getWidth())*getHeight())来进行变化,其实当前子view初始化的位置(0.0f,0.0f),也就是这时dx是0,当我进行滑动的时候,dx就递增,当前子view就开始向上移动,而相对隔壁的子view,dx是子view的宽度,dx是递减的,就开始向下移动,这个过程全都是根据每个子view的左坐标的坐标和屏幕左坐标距离进行判断的,就是越接近屏幕左坐标的就向下移动,远离就向上移动,可能我讲得也不大清楚,只要自己用纸画一下应该就会明白的,代码如下:
int saveCount = canvas.save();
int count = getChildCount();
int width = getWidth();
int scrollX=getScrollX();
// for (int i = 0; i < count; i++) {
// canvas.save();
// View view=getChildAt(i);
// int childLeft=view.getLeft();
// int dx=Math.abs(scrollX-childLeft);
// //Log.i("child"+i, x+"-----------");
// if(dx<=width){
// canvas.scale(1.0f, 1.0f-(float)0.5*dx/width);
// canvas.translate(0.0f, (0.5f*dx/width)*getHeight());
// Log.i("heigh", getHeight()+"----------");
// drawChild(canvas, view, getDrawingTime());
// canvas.restore();
// }else{
// canvas.scale(1.0f, 0.5f);
// canvas.translate(0.0f, 0.5f*getHeight());
// drawChild(canvas, view, getDrawingTime());
// canvas.restore();
// }
// }
for (int i = 0; i < count; i++) {
canvas.save();
View view=getChildAt(i);
int childLeft=view.getLeft();
int dx=Math.abs(scrollX-childLeft);
//Log.i("child"+i, dx+"-----------");
if(dx<=width){
canvas.translate(0.0f, -(1.0f*dx/width)*getHeight());
Log.i("heigh", getHeight()+"----------");
drawChild(canvas, view, getDrawingTime());
canvas.restore();
}else{
canvas.translate(0.0f, -1.0f*getHeight());
drawChild(canvas, view, getDrawingTime());
canvas.restore();
}
}
canvas.restoreToCount(saveCount);
在这个过程要注意画布的存储和恢复,不然会出现意外的(奸笑一下),其实这个效果要实现起来也是挺简单的,只是自己做的时候好像走了很多弯路,总之自己学的东西还有很多,继续努力吧!首次写开发的博客,大神们随便喷吧~
不扯那么多了,直接进入正题吧,其实实现像Launcher那样的滑动效果有几种方法,不过我在这里用继承ViewGroup的方法去实现。要是实现ViewGroup必须重写onLayout()和onMeasure()这两个方法,这个两个方法在创建的时候会自动调用,调用的顺序是onMeasure()-->onLayout()。
onMeasure()方法中是存储在ViewGroup里面每个子View的默认宽度和高度,以下代码就是把每个子View的默认宽度和高度都设置与父类的一样。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("onMeasure", "onMeasure----------");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec); //转换宽度
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("ScrollLayout only canmCurScreen run at EXACTLY mode!");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException("ScrollLayout only can run at EXACTLY mode!");
}
// 将所有的子View高度和宽度都定义成和父View一样
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
//滑动到默认屏幕
scrollTo(mCurScreen * width, 0);
}
而onLayout()就是设置每个子View在屏幕那个位置来显示出子View,现在在OnLayout()方法里面设置是从左到右横向绘出每个子View,其中onLayout这个方法的实现是在什么地方显示子view,显示的范围是多大,这个方法不能改变每个view原本的大小的
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("onLayout", "onLayout----------");
if(mTouchState == TOUCH_STATE_REST){
int childLeft = 0;//从坐标0开始绘画
final int childCount = getChildCount();
for (int i=0; i<childCount; i++) {
final View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
final int childWidth = childView.getMeasuredWidth();
//根据left , top ,right,bottom 四个参数,调用子View的layout()方法将其放置在父类中,参照物是父View
childView.layout(childLeft, 0,
childLeft+childWidth, childView.getMeasuredHeight());
childLeft += childWidth;
}
}
}
}
onMeasure和onLayout这个两个方法只是设置子View大小和绘画位置,真正把每个子View绘画出来是在onDispathDraw()方法里(一开始我还以为在onDraw,但是ViewGroup那里是不会调用onDraw方法)实现的,要是实现子view滑动时候的效果就可以再这里实现。
到了这里就把整个页面里的子view都画出来,要实现滑动的效果就需要在onTouchEvent那里做功夫,主要实现滑动动作是在MotionEvent.Action_Move里的scrollBy(x,y),x表示水平滑动的距离,y表示垂直滑动的距离,因为这里只水平方向的滑动,所以y可以设置为0。
如果要像一些桌面应用那样,当手松开后就滑动到某个完整的view的页面,这就需要用Scroller和在MotionEvent.Action_Up上设置,Scroller是可以控制整个页面的滑动,而在MotionEvent.Action_Up上面时判断手指滑动的速度,可以自己定义一个速度的基准,当达到就跨屏滑动,没有达到就判断滑动的位置是否超过当前屏幕的一半,超过就跨屏,否则仍然恢复到当前屏幕,具体还有一些数值需要自己去计算定义自己喜欢效果。代码如下:
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//获得动作捕捉器
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);//开始捕捉动作
final int action = event.getAction();
final float x = event.getX();
final float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()){
mScroller.abortAnimation();
}
mLastMotionX = x;
break;
case MotionEvent.ACTION_MOVE:
int deltaX = (int)(mLastMotionX - x);
mLastMotionX = x;
scrollBy(deltaX, 0);
break;
case MotionEvent.ACTION_UP://放手后的动作
final VelocityTracker velocityTracker = mVelocityTracker;
//计算滑动速度,参数1000表示以1000毫秒为单位计算,即以秒为单位
velocityTracker.computeCurrentVelocity(1000);
int velocityX = (int) velocityTracker.getXVelocity();
//如果向左或者向右的滑动速度超过了基础线,则直接切换屏幕;如果没有,则判断滑动的距离是否超过了屏幕一半的距离,也就是View的一半Width
if (velocityX > SNAP_VELOCITY && mCurScreen > 0) {
// Fling enough to move left
snapToScreen(mCurScreen - 1);
} else if (velocityX < -SNAP_VELOCITY
&& mCurScreen < getChildCount() - 1) {
// Fling enough to move right
snapToScreen(mCurScreen + 1);
} else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
mTouchState = TOUCH_STATE_REST;
break;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
break;
}
return true;
}
public void snapToDestination() {
final int screenWidth = getWidth();
final int destScreen = (getScrollX()+ screenWidth/2)/screenWidth;
snapToScreen(destScreen);
}
public void snapToScreen(int whichScreen) {
// get the valid layout page
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount()-1));
if (getScrollX() != (whichScreen*getWidth())) {
final int delta = whichScreen*getWidth()-getScrollX();
mScroller.startScroll(getScrollX(), 0,
delta, 0, Math.abs(delta)*2);
mCurScreen = whichScreen;
invalidate(); // Redraw the layout
}
}
现在基本算是实现了整个屏幕滑动的效果,要实现滑动的动画就必须要在dispathDraw(Canvas canvas)的canvas来实现了,在ViewGroup里面有一个方法drawChild(),通过这个将每个view都重绘上去,其中的变换不外乎translate,scale这个几种,当然要实现其他比较复杂的效果就需要其他操作了,所以现在要重写dispatchDraw里面的方法,而我现在要实现像Go桌面那样的弹跳效果,这里是通过获取屏幕的左位置和每个子view的左坐标来进行绘画,因为子view的位置是固定的,而屏幕的左坐标却在不断的变化。在这里是用一个判断为基准,就是每个子view的左坐标与屏幕左坐标的距离是否超过一个子view的宽度,超过距离的子view将不做变换。
int dx=Math.abs(getScrollX()-view.getLeft())通过这个获取每个子view的左坐标和屏幕左坐标的距离,这里我是实现弹跳的效果,其实只是对子view的y轴上的位置进行变换,用dx/view.getWidth()来获取滑动距离的比例,通过canvas.translate(0.0f, -(1.0f*dx/view.getWidth())*getHeight())来进行变化,其实当前子view初始化的位置(0.0f,0.0f),也就是这时dx是0,当我进行滑动的时候,dx就递增,当前子view就开始向上移动,而相对隔壁的子view,dx是子view的宽度,dx是递减的,就开始向下移动,这个过程全都是根据每个子view的左坐标的坐标和屏幕左坐标距离进行判断的,就是越接近屏幕左坐标的就向下移动,远离就向上移动,可能我讲得也不大清楚,只要自己用纸画一下应该就会明白的,代码如下:
int saveCount = canvas.save();
int count = getChildCount();
int width = getWidth();
int scrollX=getScrollX();
// for (int i = 0; i < count; i++) {
// canvas.save();
// View view=getChildAt(i);
// int childLeft=view.getLeft();
// int dx=Math.abs(scrollX-childLeft);
// //Log.i("child"+i, x+"-----------");
// if(dx<=width){
// canvas.scale(1.0f, 1.0f-(float)0.5*dx/width);
// canvas.translate(0.0f, (0.5f*dx/width)*getHeight());
// Log.i("heigh", getHeight()+"----------");
// drawChild(canvas, view, getDrawingTime());
// canvas.restore();
// }else{
// canvas.scale(1.0f, 0.5f);
// canvas.translate(0.0f, 0.5f*getHeight());
// drawChild(canvas, view, getDrawingTime());
// canvas.restore();
// }
// }
for (int i = 0; i < count; i++) {
canvas.save();
View view=getChildAt(i);
int childLeft=view.getLeft();
int dx=Math.abs(scrollX-childLeft);
//Log.i("child"+i, dx+"-----------");
if(dx<=width){
canvas.translate(0.0f, -(1.0f*dx/width)*getHeight());
Log.i("heigh", getHeight()+"----------");
drawChild(canvas, view, getDrawingTime());
canvas.restore();
}else{
canvas.translate(0.0f, -1.0f*getHeight());
drawChild(canvas, view, getDrawingTime());
canvas.restore();
}
}
canvas.restoreToCount(saveCount);
在这个过程要注意画布的存储和恢复,不然会出现意外的(奸笑一下),其实这个效果要实现起来也是挺简单的,只是自己做的时候好像走了很多弯路,总之自己学的东西还有很多,继续努力吧!首次写开发的博客,大神们随便喷吧~
发表评论
-
ListView与Button、imageButton 的共存问题解决
2013-02-20 11:39 1301ListView与Button、imageButton 的共存 ... -
android实现popupwindow的动画效果
2013-02-01 18:56 1989问题:在打开或者关闭popupwindow的时候怎么样显示动画 ... -
Android开发ViewPager中ListView失效问题解决方法
2013-01-28 22:12 2747最近开发一个Android小应用。就是利用ViewPager实 ... -
关于WebView的loadData方法以及乱码问题
2012-08-09 14:37 951WebView是Android应用开发 ... -
Android对图片的压缩读取和保存
2012-08-08 10:27 1367在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情 ... -
ubuntu下载android源代码
2012-07-22 00:50 1892用虚拟机来创建一个Ubun ... -
android面试(2)
2012-07-20 16:17 1061附带答案,共100分 一、选择题(30题,每题1.5分,共4 ... -
自定义PreferenceActivity——修改Preference样式、加顶部布局
2012-05-27 20:19 2682首先在res/xml文件夹下建立preferences.xml ... -
android拦截短信并屏蔽系统的Notification
2012-05-21 09:25 1780Android短信拦截,总的来说有两种方式: (一)、在代码 ... -
Android设置应用程序默认语言
2012-05-19 21:03 1517Android应用程序的国际化还是做得不错的,通过设置资源文件 ... -
(android 实战总结)android对html支持接口总结
2012-04-18 09:50 2368Android支持html 的两个接口 1 Spanned ... -
Android的TextView使用Html来处理图片显示、字体样式、超链接等
2012-04-16 11:09 1545转eoe:http://www.eoeandroid.com/ ... -
android的ant编译打包
2012-04-11 14:52 3893Android本身是支持ant打包项目的,并且SDK中自带一个 ... -
使用InputStreamEntity 边读取边上传文件
2012-04-09 17:32 7402HttpClient httpclient = new Def ... -
android xliff字符串操作
2012-04-09 14:59 1406参考:http://blog.csdn.net/freshma ... -
Android:只读EditText内容可滚动(禁止输入法)的实现
2012-04-06 12:00 1384实验设备为HTC hero (SDK 2.1-update1) ... -
Eclipse报内存溢出
2012-04-04 10:50 1090(1)在配置tomcat的JDK里面设置。Window--&g ... -
Android解压缩zip的实现
2012-03-20 11:21 2817android 解压缩zip包,需要在menifest.xml ... -
Android alertdialog的按钮点击后不消失
2012-03-15 20:35 1857使用反射: 在你的setPositiveButton中添加 ... -
Android 读取<meta-data>元素的数据
2012-03-05 13:47 1936在AndroidManifest.xml中,<meta- ...
相关推荐
使用ViewGroup实现微信左右滑动切换界面以及界面裂开的效果
本文实例讲述了Android继承ViewGroup实现Scroll滑动效果的方法。分享给大家供大家参考,具体如下: extends ViewGroup需要重写onMeasure和onLayout方法 onMeasure方法是去测量ViewGroup需要的大小以及包含的子View...
主要为大家详细介绍了Android自定义ViewGroup实现弹性滑动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Android 跑马灯 ,用 viewgroup + 动画实现,参见文章http://blog.csdn.net/u012587637/article/details/41694765
HorizontalScrollView与ViewGroup实现横向滑动查看图片
ViewGroup实现九宫格并可拖动位置
详细请看:http://blog.csdn.net/dawanganban/article/details/24007215
完全自定义ViewGroup ,实现ViewPager滑动效果.
这是android viewgroup view 源码,有一些注释,此源码仅供学习使用。
Android实现的ViewGroup双向滑动界面效果,这在当下的各种android客户端应用中使用广泛,操作也是比较顺手的一种方式,本滑动界面中设置右滑的菜单View、设置主界面View、并设置了菜单和内容边界,定义好这些为下...
该资源包含了一个利用自定义的viewgroup实现的slidingmenu,简单易懂。
该Demo是来源于网上,作者继承ViewGroup写了一个自定义的ViewGroup,来实现ViewPager的滑动效果(在当前屏幕未全部滑出去时,下一屏幕会显示在当前屏幕上),因为ViewPager一般用于Activity或者Fragment,但是我们...
Android 自定义ViewGroup实现整个Item布局竖直跑马灯效果,详细看我的博客讲解
前面在学习鸿洋大神的一些自定义的View文章,看到了自定义ViewGroup实现浮动标签,初步看了下他的思路以及结合自己的思路完成了自己的浮动标签的自定义ViewGroup。目前实现的可以动态添加标签、可点击。效果图如下:...
android自定义viewgroup实现等分格子布局
主要介绍了Android自定义viewGroup实现点击动画效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
ViewPager+自定义ViewGroup来实现同时支持上下左右切屏。ViewPager实现左右切屏,ViewGroup负责上下切屏。