使用HorizontalScrollView实现瑞士军刀界面
2014-11-17 11:22
295 查看
iOS及Android上的瑞士军刀界面很是新颖,也很便捷。很多应用采用了该设计,例如QQ,凤凰新闻客户端等。今天介绍一下通过自定义HorizontalScrollView类的方法实现瑞士军刀界面。
★依赖jar包
NineOldAndroids.jar
★思路:
●使用HorizontalScrollView布局,左侧为Menu,右侧为Content;
自定义HorizontalScrollView,使之监听Action_UP事件,进行Menu的显示和隐藏;
●menu隐藏在抽屉正下方
属性动画:改变拖动时,
调用动画时机:ACTION_MOVE==>覆写View类的onScrollChanged()方法
●菜单及内容区域的缩放和透明度变化
拖动时 scale:1.0-0
menu透明度变化:0.7-1.0
menu缩放变化:0.7-1.0
content缩放变化:1.0-0.7【注意默认缩放中心会影响实际效果,需要设置缩放中心】
★效果图
★核心代码实现
JAVA中自定义HorizontalScrollView类:SlidingMenu
------------------------------------------------------------------
public class SlidingMenu extends HorizontalScrollView{
private LinearLayout mWrapper;
private ViewGroup mMenu;
private ViewGroup mContent;
private int menuWidth;
private int slidingMenuPadding;
private int screenWidth;
private boolean once;
private boolean isOpen;
public SlidingMenu(Context context, AttributeSet attr) {
super(context, attr);
DisplayMetrics dm = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
slidingMenuPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80,
context.getResources().getDisplayMetrics());
}
/**
* 初始化Menu的位置
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.e("SLIDING","onLayout()");
//if (!changed){
Log.e("SLIDING","onLayout() !changed");
this.scrollTo(menuWidth, 0);
//}
super.onLayout(changed, l, t, r, b);
}
/**
* 设置HorizontalScrollView自己的宽度和高度及子View的宽度高度
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.e("SLIDING","onMeasure()");
if (!once){
mWrapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWrapper.getChildAt(0);
mContent = (ViewGroup) mWrapper.getChildAt(1);
menuWidth = mMenu.getLayoutParams().width = screenWidth - slidingMenuPadding;
mContent.getLayoutParams().width = screenWidth;
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 监听触摸事件,并在手指提起时触发menu的显示或隐藏
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.e("SLIDING","onTouchEvent()");
int action = ev.getAction();
switch (action){
case MotionEvent.ACTION_UP:
Log.e("SLIDING","onMeasure() ACTION_UP");
// scrollX是横向偏移的X轴坐标,随着手的右向滑动,该数值在变小
int scrollX = getScrollX();
if (scrollX >= menuWidth/2){
// 隐藏menu
Log.e("SLIDING","onMeasure() ACTION_UP menuWidth");
this.smoothScrollTo(menuWidth, 0);
isOpen = false;
} else {
// 显示menu
Log.e("SLIDING","onMeasure() ACTION_UP 0");
this.smoothScrollTo(0,0);
isOpen = true;
}
return true;
}
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
// 调用属性动画,设置TranslationX,需要使用第三方
4000
jar包
// 定义scroll数值的变化域 scale:1-0
float scale = l * 1.0f/menuWidth;
// 定义content缩放域:1.0-0.7
float rightScale = 0.7f + scale * 0.3f;
// 定义Menu的缩放域 0.7-1.0
float leftScale = 1.0f - scale * 0.3f;
// 设置menu的透明度变化域 0.7-1.0
float leftAlpha = 1.0f - scale * 0.3f;
// menu跟随手指移动(0.5f为更改menu显示时的位置)
ViewHelper.setTranslationX(mMenu, l * 0.5f);
// 对menu进行缩放和透明度变化指定
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
ViewHelper.setAlpha(mMenu, leftAlpha);
// 对content进行横纵缩放
// 设置content缩放中心为屏幕左侧中心点
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight()/2);
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
public void trigger(){
if (isOpen){
closeMenu();
isOpen = false;
} else {
openMenu();
isOpen = true;
}
}
private void openMenu(){
if (isOpen) return;
this.smoothScrollTo(0,0);
}
private void closeMenu(){
if (!isOpen) return;
this.smoothScrollTo(menuWidth, 0);
}
}
★参考布局
主界面:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/leaf" >
<!--android:scrollbars="none" 去除滚动条 -->
<com.example.dialogtest.SlidingMenu
android:id="@+id/menu_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" >
<include layout="@layout/sliding_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/apple" >
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/title_bar_menu"
android:onClick="showMenu" />
</LinearLayout>
</LinearLayout>
</com.example.dialogtest.SlidingMenu>
</RelativeLayout>
★依赖jar包
NineOldAndroids.jar
★思路:
●使用HorizontalScrollView布局,左侧为Menu,右侧为Content;
自定义HorizontalScrollView,使之监听Action_UP事件,进行Menu的显示和隐藏;
●menu隐藏在抽屉正下方
属性动画:改变拖动时,
调用动画时机:ACTION_MOVE==>覆写View类的onScrollChanged()方法
●菜单及内容区域的缩放和透明度变化
拖动时 scale:1.0-0
menu透明度变化:0.7-1.0
menu缩放变化:0.7-1.0
content缩放变化:1.0-0.7【注意默认缩放中心会影响实际效果,需要设置缩放中心】
★效果图
★核心代码实现
JAVA中自定义HorizontalScrollView类:SlidingMenu
------------------------------------------------------------------
public class SlidingMenu extends HorizontalScrollView{
private LinearLayout mWrapper;
private ViewGroup mMenu;
private ViewGroup mContent;
private int menuWidth;
private int slidingMenuPadding;
private int screenWidth;
private boolean once;
private boolean isOpen;
public SlidingMenu(Context context, AttributeSet attr) {
super(context, attr);
DisplayMetrics dm = new DisplayMetrics();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
slidingMenuPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80,
context.getResources().getDisplayMetrics());
}
/**
* 初始化Menu的位置
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.e("SLIDING","onLayout()");
//if (!changed){
Log.e("SLIDING","onLayout() !changed");
this.scrollTo(menuWidth, 0);
//}
super.onLayout(changed, l, t, r, b);
}
/**
* 设置HorizontalScrollView自己的宽度和高度及子View的宽度高度
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.e("SLIDING","onMeasure()");
if (!once){
mWrapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWrapper.getChildAt(0);
mContent = (ViewGroup) mWrapper.getChildAt(1);
menuWidth = mMenu.getLayoutParams().width = screenWidth - slidingMenuPadding;
mContent.getLayoutParams().width = screenWidth;
once = true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 监听触摸事件,并在手指提起时触发menu的显示或隐藏
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.e("SLIDING","onTouchEvent()");
int action = ev.getAction();
switch (action){
case MotionEvent.ACTION_UP:
Log.e("SLIDING","onMeasure() ACTION_UP");
// scrollX是横向偏移的X轴坐标,随着手的右向滑动,该数值在变小
int scrollX = getScrollX();
if (scrollX >= menuWidth/2){
// 隐藏menu
Log.e("SLIDING","onMeasure() ACTION_UP menuWidth");
this.smoothScrollTo(menuWidth, 0);
isOpen = false;
} else {
// 显示menu
Log.e("SLIDING","onMeasure() ACTION_UP 0");
this.smoothScrollTo(0,0);
isOpen = true;
}
return true;
}
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
// 调用属性动画,设置TranslationX,需要使用第三方
4000
jar包
// 定义scroll数值的变化域 scale:1-0
float scale = l * 1.0f/menuWidth;
// 定义content缩放域:1.0-0.7
float rightScale = 0.7f + scale * 0.3f;
// 定义Menu的缩放域 0.7-1.0
float leftScale = 1.0f - scale * 0.3f;
// 设置menu的透明度变化域 0.7-1.0
float leftAlpha = 1.0f - scale * 0.3f;
// menu跟随手指移动(0.5f为更改menu显示时的位置)
ViewHelper.setTranslationX(mMenu, l * 0.5f);
// 对menu进行缩放和透明度变化指定
ViewHelper.setScaleX(mMenu, leftScale);
ViewHelper.setScaleY(mMenu, leftScale);
ViewHelper.setAlpha(mMenu, leftAlpha);
// 对content进行横纵缩放
// 设置content缩放中心为屏幕左侧中心点
ViewHelper.setPivotX(mContent, 0);
ViewHelper.setPivotY(mContent, mContent.getHeight()/2);
ViewHelper.setScaleX(mContent, rightScale);
ViewHelper.setScaleY(mContent, rightScale);
}
public void trigger(){
if (isOpen){
closeMenu();
isOpen = false;
} else {
openMenu();
isOpen = true;
}
}
private void openMenu(){
if (isOpen) return;
this.smoothScrollTo(0,0);
}
private void closeMenu(){
if (!isOpen) return;
this.smoothScrollTo(menuWidth, 0);
}
}
★参考布局
主界面:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/leaf" >
<!--android:scrollbars="none" 去除滚动条 -->
<com.example.dialogtest.SlidingMenu
android:id="@+id/menu_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" >
<include layout="@layout/sliding_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/apple" >
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/title_bar_menu"
android:onClick="showMenu" />
</LinearLayout>
</LinearLayout>
</com.example.dialogtest.SlidingMenu>
</RelativeLayout>
相关文章推荐
- [Android]使用HorizontalScrollView实现广告栏Banner及相关原理分析
- android 使用HorizontalScrollView 实现标题带动内容左右切屏
- 使用HorizontalScrollView实现水平控件拖动效果
- 使用HorizontalScrollView实现侧滑ListView
- 使用HorizontalScrollView实现侧滑效果(1)
- Android 使用HorizontalScrollView 实现Gallery效果
- 使用HorizontalScrollView 实现ListView横向滑动
- 51.使用HorizontalScrollView+LinearLayout实现文字+图片的自动跑马灯效果
- Android 使用HorizontalScrollView 实现图片画廊
- HorizontalScrollView 使用 实现textview和viewpager的联动
- 使用HorizontalScrollView简单实现柱状图
- 使用HorizontalScrollView实现侧滑效果(2)
- 使用HorizontalScrollView实现最简单的侧滑菜单
- 使用HorizontalScrollView实现侧滑效果(3)
- 使用HorizontalScrollView实现侧滑菜单
- 使用 HorizontalScrollView 实现水平滚动,并点击有相应的反应效果
- 使用 HorizontalScrollView 实现滚动控制
- 使用XIB自定义一个UIView,然后将这个view添加到controller的view 上(相当于所有界面都通过xib来实现)
- 布局动画Android ScrollView HorizontalScrollView 实现全方向(上下左右)反弹效果
- 实现android左右滑动效果:ViewFlipper、ViewPager、HorizontalScrollView