QQ主界面的滑动效果的实现(xml中定义布局属性)
2015-09-17 20:37
519 查看
需要注意的时本例中导入了com.nineoldandroids.view.ViewHelper的包,还用到了常用的ScreenUtils 辅助类来获取屏幕的信息。jar包可以在网盘中寻找。
更高级用法:/article/1580285.html
神级用法:/article/1336224.html
所以在以后的实践中要注意jar的使用,以及常用辅助类的总结
[html] view plaincopy在CODE上查看代码片派生到我的代码片
float scale = l * 1.0f / mMenuWidth;
与菜单的宽度做除法运算,在菜单隐藏到显示整个过程,会得到1.0~0.0这么个变化的区间;
有了这个区间,就可以根据这个区间设置动画了;
1、首先是内容区域的缩放比例计算:
我们准备让在菜单出现的过程中,让内容区域从1.0~0.8进行变化~~
那么怎么把1.0~0.0转化为1.0~0.8呢,其实很简单了:
float rightScale = 0.8f + scale * 0.2f; (scale 从1到0 ),是不是哦了~
接下来还有3个动画:
2、菜单的缩放比例计算
仔细观察了下QQ,菜单大概缩放变化是0.7~1.0
float leftScale = 1 - 0.3f * scale;
3、菜单的透明度比例:
我们设置为0.6~1.0;即:0.6f + 0.4f * (1 - scale)
4、菜单的x方向偏移量:
看一下QQ,并非完全从被内容区域覆盖,还是有一点拖出的感觉,所以我们的偏移量这么设置:
tranlateX = mMenuWidth * scale * 0.6f ;刚开始还是让它隐藏一点点~~~
另外,关于动画可参考http://code1.okbase.net/codefile/ViewHelper.java_2014032025926_38.htm
本文参照:/article/1336229.html更高级用法:/article/1580285.html
神级用法:/article/1336224.html
所以在以后的实践中要注意jar的使用,以及常用辅助类的总结
主程序
package com.test.mysideslip; import android.support.v7.app.ActionBarActivity; import com.test.sideslip.SlidingMenu; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.widget.LinearLayout; public class MainActivity extends Activity { private SlidingMenu mMenu; private LinearLayout mLinearLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mMenu = (SlidingMenu) findViewById(R.id.id_menu); } public void toggle_Menu(View view) { mMenu.toggle(); } public void linear_toggle_Menu(View view){ //实现一点击主页面时,就进入主页面 mMenu.toggle(); } }
滑动效果实现的主要程序
package com.test.sideslip; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import com.nineoldandroids.view.ViewHelper; import com.test.mysideslip.R; public class SlidingMenu extends HorizontalScrollView { /** * 屏幕宽度 */ private int mScreenWidth; /** * dp */ private int mMenuRightPadding; /** * 开始隐藏菜单的宽度 */ private int mMenuWidth; private int mHalfMenuWidth; private boolean isOpen; private boolean once; private ViewGroup mMenu; private ViewGroup mContent; public SlidingMenu(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingMenu(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mScreenWidth = ScreenUtils.getScreenWidth(context); //类型的数组,得到所有theme //Sliding属性是定义在xml文件中的 TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SlidingMenu, defStyle, 0); int n = a.getIndexCount(); for (int i = 0; i < n; i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.SlidingMenu_rightPadding: // 默认50,后面传入的为默认值 mMenuRightPadding = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 50f, getResources().getDisplayMetrics())); break; } } a.recycle(); } public SlidingMenu(Context context) { this(context, null, 0); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 显示的设置一个宽度 */ if (!once) { LinearLayout wrapper = (LinearLayout) getChildAt(0); mMenu = (ViewGroup) wrapper.getChildAt(0); mContent = (ViewGroup) wrapper.getChildAt(1); //需要注意的mMenuWidth是屏幕的总宽度减去已经隐藏起来的右边内容的宽度 //所以mMenuWidth会越来越小。 mMenuWidth = mScreenWidth - mMenuRightPadding; mHalfMenuWidth = mMenuWidth / 2; mMenu.getLayoutParams().width = mMenuWidth; //在屏幕上显示的部分 mContent.getLayoutParams().width = mScreenWidth; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * 布局发生变化时调用的方法 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { // 将菜单隐藏 this.scrollTo(mMenuWidth, 0); once = true; } } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { // Up时,进行判断,如果显示区域大于菜单宽度一半则完全显示,否则隐藏 case MotionEvent.ACTION_UP: int scrollX = getScrollX(); if (scrollX > mHalfMenuWidth) { //菜单就是最开始的隐藏部分 this.smoothScrollTo(mMenuWidth, 0); isOpen = false; } else { this.smoothScrollTo(0, 0); isOpen = true; } return true; } return super.onTouchEvent(ev); } //下面的三个方法完全是为了左上角的按钮切换。 /** * 打开菜单 */ public void openMenu() { if (isOpen) return; this.smoothScrollTo(0, 0); isOpen = true; } /** * 关闭菜单 */ public void closeMenu() { if (isOpen) { this.smoothScrollTo(mMenuWidth, 0); isOpen = false; } } /** * 切换菜单状态 */ public void toggle() { if (isOpen) { closeMenu(); } else { openMenu(); } } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); //得到左边隐藏宽度的单位宽度 float scale = l * 1.0f / mMenuWidth; //左边的缩小比例 float leftScale = 1 - 0.3f * scale; //右边的缩小比例 float rightScale = 0.8f + scale * 0.2f; //放大缩小布局文件 ViewHelper.setScaleX(mMenu, leftScale); ViewHelper.setScaleY(mMenu, leftScale); ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale)); ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.6f); //设置缩放的中心线,就是scale时沿哪条中心线进行缩放。 ViewHelper.setPivotX(mContent, 0); ViewHelper.setPivotY(mContent, mContent.getHeight()/2 ); //之所以用这个值的原因已经在onMeasure中解释 ViewHelper.setScaleX(mContent, rightScale); ViewHelper.setScaleY(mContent, rightScale); } }
屏幕测量辅助类
package com.test.sideslip; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.View; import android.view.WindowManager; public class ScreenUtils { private ScreenUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * 获得屏幕高度 * * @param context * @return */ public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * 获得屏幕宽度 * * @param context * @return */ public static int getScreenHeight(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } /** * 获得状态栏的高度 * * @param context * @return */ public static int getStatusHeight(Context context) { int statusHeight = -1; try { Class<?> clazz = Class.forName("com.android.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printStackTrace(); } return statusHeight; } /** * 获取当前屏幕截图,包含状态栏 * * @param activity * @return */ public static Bitmap snapShotWithStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, 0, width, height); view.destroyDrawingCache(); return bp; } /** * 获取当前屏幕截图,不包含状态栏 * * @param activity * @return */ public static Bitmap snapShotWithoutStatusBar(Activity activity) { View view = activity.getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bmp = view.getDrawingCache(); Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top; int width = getScreenWidth(activity); int height = getScreenHeight(activity); Bitmap bp = null; bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight); view.destroyDrawingCache(); return bp; } }
主布局文件
<com.test.sideslip.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:zhy="http://schemas.android.com/apk/res/com.test.mysideslip" android:layout_width="wrap_content" android:layout_height="fill_parent" android:scrollbars="none" android:id="@+id/id_menu" zhy:rightPadding="100dp" android:background="@drawable/c" > <LinearLayout android:layout_width="wrap_content" android:layout_height="fill_parent" android:orientation="horizontal" > <include layout="@layout/layout_menu" /> <LinearLayout android:id="@+id/main_pager_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/c" android:onClick="linear_toggle_Menu" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="toggle_Menu" android:text="切换菜单" /> </LinearLayout> </LinearLayout> </com.test.sideslip.SlidingMenu>
layout_menu.xml布局文件
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/one" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@drawable/c" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@id/one" android:text="第1个Item" android:textColor="#f0f0f0" android:textSize="20sp" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/two" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@drawable/b" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@id/two" android:text="第2个Item" android:textColor="#f0f0f0" android:textSize="20sp" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/three" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@drawable/b" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@id/three" android:text="第3个Item" android:textColor="#f0f0f0" android:textSize="20sp" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/four" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@drawable/b" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@id/four" android:text="第一个Item" android:textColor="#f0f0f0" android:textSize="20sp" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/five" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@drawable/b" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@id/five" android:text="第5个Item" android:textColor="#f0f0f0" android:textSize="20sp" /> </RelativeLayout> </LinearLayout> </RelativeLayout>
效果图
当这样写时可以实现另一种效果
@Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); float scale = l * 1.0f / mMenuWidth; // float leftScale = 1 - 0.3f * scale; // float rightScale = 0.8f + scale * 0.2f; // // ViewHelper.setScaleX(mMenu, leftScale); // ViewHelper.setScaleY(mMenu, leftScale); // ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale)); ViewHelper.setTranslationX(mMenu, mMenuWidth * scale ); // ViewHelper.setPivotX(mContent, 0); // ViewHelper.setPivotY(mContent, mContent.getHeight() / 2); // ViewHelper.setScaleX(mContent, rightScale); // ViewHelper.setScaleY(mContent, rightScale); }
3、动画比例的计算
我们在onScrollChanged里面,拿到 l 也就是个getScrollX,即菜单已经显示的宽度值;[html] view plaincopy在CODE上查看代码片派生到我的代码片
float scale = l * 1.0f / mMenuWidth;
与菜单的宽度做除法运算,在菜单隐藏到显示整个过程,会得到1.0~0.0这么个变化的区间;
有了这个区间,就可以根据这个区间设置动画了;
1、首先是内容区域的缩放比例计算:
我们准备让在菜单出现的过程中,让内容区域从1.0~0.8进行变化~~
那么怎么把1.0~0.0转化为1.0~0.8呢,其实很简单了:
float rightScale = 0.8f + scale * 0.2f; (scale 从1到0 ),是不是哦了~
接下来还有3个动画:
2、菜单的缩放比例计算
仔细观察了下QQ,菜单大概缩放变化是0.7~1.0
float leftScale = 1 - 0.3f * scale;
3、菜单的透明度比例:
我们设置为0.6~1.0;即:0.6f + 0.4f * (1 - scale)
4、菜单的x方向偏移量:
看一下QQ,并非完全从被内容区域覆盖,还是有一点拖出的感觉,所以我们的偏移量这么设置:
tranlateX = mMenuWidth * scale * 0.6f ;刚开始还是让它隐藏一点点~~~
相关文章推荐
- java 不寻常的问题 No bean named 'sessionFactory' is defined 和 initialize a collection of role
- HDU---5441-Travel(并查集)(2015 Changchun)
- HDU 2102 A计划
- 0917Android基础自定义View(Path)
- swift 日历练习
- ios9键盘回调与消息通知,理论上应该是个bug
- 大话移动app测试_阅读
- 以树形结构的形式输出指定目录下面的所有文件
- 优秀IT技术文章集(最新)(高质量)
- CGS flip 学习总结
- bash shell基础之一
- android学习:service 绑定,与服务进行通信
- EPEL&&Yum Priorities
- git 文件删除与恢复
- XML文件在TwinCAT里面的作用
- 找出一组数据中多次出现的所有数字(空间要求最低)
- 浅谈数据结构-归并排序
- test4.1
- VS2013 快捷键乱掉如何修改回来
- 移动王国的诱惑【经济学人】