1.基础知识
1.1HorizontalScrollView是一个 FrameLayout , 这意味着你只能在它下面放置一个子控件 ,这个子控件可以包含很多数据内容。有可能这个子控件本身就是一个布局控件,可以包含非常多的其他用来展示数据的控件。
继承HorizontalScrollView(水平滑动控件)
需要 重写onMeasure,onLayout , onTouchEvent方法
onMeasure中设置子view的大小和本身的大小
onLayout 需要布局子view和自身的位置
onTouchEvent 触动处理
1.2.
scrollTo(int x,int y):
如果偏移位置发生了改变,就会给mScrollX和mScrollY赋新值,改变当前位置。
注意:x,y代表的不是坐标点,而是偏移量。
例如:
我要移动view到坐标点(100,100),那么我的偏移量就是(0,,0) - (100,100) = (-100 ,-100) ,我就要执行view.scrollTo(-100,-100),达到这个效果。
scrollBy(int x,int y):
从源码中看出,它实际上是调用了scrollTo(mScrollX + x, mScrollY + y);
mScrollX + x和mScrollY + y,即表示在原先偏移的基础上在发生偏移,通俗的说就是相对我们当前位置偏移。
根据父类VIEW里面移动,如果移动到了超出的地方,就不会显示。
查看上文中的示意图你就会知道大概。
2.开发
<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_centerInParent="true"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/menu_img1"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/menu_tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/menu_img1"
android:text="第一个item"
android:layout_centerVertical="true"
/>
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/menu_img2"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/menu_tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/menu_img2"
android:text="第2个item"
android:layout_centerVertical="true"
/>
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/menu_img3"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/menu_tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/menu_img3"
android:text="第3个item"
android:layout_centerVertical="true"
/>
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/menu_img4"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/ic_launcher"
/>
<TextView
android:id="@+id/menu_tv4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/menu_img4"
android:text="第4个item"
android:layout_centerVertical="true"
/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.hzs.view.MenuSlidingView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<include layout="@layout/left_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/content"
>
</LinearLayout>
</LinearLayout>
</com.hzs.view.MenuSlidingView >
</RelativeLayout>
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class MenuSlidingView extends HorizontalScrollView {
//HorizontalScrollView中只有一个布局
private LinearLayout linearLayout;
//定义左菜单
private ViewGroup mMenu;
//定义内容
private ViewGroup mContent;
//定义频幕宽度
private int mScreenWidth;
//定义menu的宽度
private int mMenuWidth;
//定义menu距离右侧的宽度
private int mMenuRightPadding=50;
private boolean once=false;
public MenuSlidingView(Context context, AttributeSet attrs) {
super(context, attrs);
//获取频幕宽度
WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics=new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth=outMetrics.widthPixels;
//使用TypeValue将dp转换成px
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
}
/**
* 设置子view的宽和高,设置自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!once){
//获取第一个布局元素
linearLayout=(LinearLayout) getChildAt(0);
//获取linerLayout的第一元素
mMenu=(ViewGroup) linearLayout.getChildAt(0);
//获取linerLayout的第一元素
mContent=(ViewGroup) linearLayout.getChildAt(1);
mMenuWidth=mMenu.getLayoutParams().width=mScreenWidth-mMenuRightPadding;
mContent.getLayoutParams().width=mScreenWidth;
once=true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 通过设置偏移量,将menu隐藏
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
if(changed){
this.scrollBy(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action=ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
int scrollX=getScrollX();
if( scrollX > mMenuWidth / 2 ){
this.smoothScrollTo(mMenuWidth, 0);
}else{
this.smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
}
2.3mainActivity
package com.hzs.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class MenuSlidingView extends HorizontalScrollView {
//HorizontalScrollView中只有一个布局
private LinearLayout linearLayout;
//定义左菜单
private ViewGroup mMenu;
//定义内容
private ViewGroup mContent;
//定义频幕宽度
private int mScreenWidth;
//定义menu的宽度
private int mMenuWidth;
//定义menu距离右侧的宽度
private int mMenuRightPadding=50;
private boolean once=false;
public MenuSlidingView(Context context, AttributeSet attrs) {
super(context, attrs);
//获取频幕宽度
WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics=new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWidth=outMetrics.widthPixels;
//使用TypeValue将dp转换成px
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources().getDisplayMetrics());
}
/**
* 设置子view的宽和高,设置自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!once){
//获取第一个布局元素
linearLayout=(LinearLayout) getChildAt(0);
//获取linerLayout的第一元素
mMenu=(ViewGroup) linearLayout.getChildAt(0);
//获取linerLayout的第一元素
mContent=(ViewGroup) linearLayout.getChildAt(1);
mMenuWidth=mMenu.getLayoutParams().width=mScreenWidth-mMenuRightPadding;
mContent.getLayoutParams().width=mScreenWidth;
once=true;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 通过设置偏移量,将menu隐藏
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
if(changed){
this.scrollBy(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action=ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
int scrollX=getScrollX();
if( scrollX > mMenuWidth / 2 ){
this.smoothScrollTo(mMenuWidth, 0);
}else{
this.smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
}