AndroidUI-仿QQ侧滑例子(简单版)
在此感谢hyman大神的博客教程,让在下受益匪浅。
鸿洋老师的博客
运行效果:
主要用到的知识点:
- 自定义View组件继承HorizontalScrollView
1.需要获取屏幕的像素
2.设置左侧菜单布局的宽度
3.设置手指抬起事件
4.单位的转换(dp->px)
5.设置组件的位置(onLayout(boolean changed, int l, int t, int r, int b))
首先是设置左侧菜单的布局
left_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"
android:background="@drawable/menu_background" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img1"
android:text="第一个item"
android:textColor="#ffffff"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img2"
android:text="第二个item"
android:textColor="#ffffff"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img3"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img3"
android:text="第三个item"
android:textColor="#ffffff"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img4"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img4"
android:text="第四个item"
android:textColor="#ffffff"
android:textSize="20sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/id_img5"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:src="@drawable/img_5" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@id/id_img5"
android:text="第五个item"
android:textColor="#ffffff"
android:textSize="20sp" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
还有就是activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- 之后继承HorizontalScrollView的类 -->
<com.example.again_imooc_qq50_demo.view.MyMenuView
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/left_menu" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/qq" >
</LinearLayout>
</LinearLayout>
</com.example.again_imooc_qq50_demo.view.MyMenuView>
</RelativeLayout>
接下来就是继承HorizontalScrollView自定义View类了
首先定义全局变量
private int sCreenWidth; // 屏幕像素的宽度
private int mMenuRightPadding; // 菜单和右边的边距
private int mMenuWidth; // 菜单布局的宽度
private boolean once = true;
/**
* 各个组件
*/
private LinearLayout mWapper;
private ViewGroup mMenu;
private ViewGroup mContent;
1.获取屏幕像素
/**
* 获取屏幕像素的宽度值
*
* @param context
* @param attrs
*/
public MyMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
// 屏幕像素的PX
sCreenWidth = outMetrics.widthPixels;
/**
* 进行单位的转换 dp->px
*/
mMenuRightPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
.getDisplayMetrics());
}
mMenuRightPadding代表的宽度->如下图所示
首先设置一个布尔型变量
/**
* 为了避免onMeasure方法多次调用 我们设置一个布尔值
*/
private boolean once = true;
2.决定View的宽和高
/**
* 决定View的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (once) {
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
// 菜单布局的宽度
mMenuWidth = mMenu.getLayoutParams().width = sCreenWidth
- mMenuRightPadding;
mContent.getLayoutParams().width = sCreenWidth;
once = false;
}
}
3.决定组件在什么位置
/**
* 决定组件在什么位置
*/
@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) {
scrollTo(mMenuWidth, 0);
}
}
接下来就是设置手指抬起的事件了
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
// 隐藏在左边的宽度
int scrollX = getScrollX();
if (scrollX <= mMenuWidth / 2) {
smoothScrollTo(0, 0);
} else {
smoothScrollTo(mMenuWidth, 0);
}
return true;
default:
break;
}
return super.onTouchEvent(ev);
}
完整代码:
MyMenuView.java
package com.example.again_imooc_qq50_demo.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 MyMenuView extends HorizontalScrollView {
private int sCreenWidth; // 屏幕像素的宽度
private int mMenuRightPadding; // 菜单和右边的边距
private int mMenuWidth; // 菜单布局的宽度
private boolean once = true;
/**
* 各个组件
*/
private LinearLayout mWapper;
private ViewGroup mMenu;
private ViewGroup mContent;
/**
* 获取屏幕像素的宽度值
*
* @param context
* @param attrs
*/
public MyMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
// 屏幕像素的PX
sCreenWidth = outMetrics.widthPixels;
/**
* 进行单位的转换 dp->px
*/
mMenuRightPadding = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, context.getResources()
.getDisplayMetrics());
}
/**
* 决定View的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (once) {
mWapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) mWapper.getChildAt(0);
mContent = (ViewGroup) mWapper.getChildAt(1);
// 菜单布局的宽度
mMenuWidth = mMenu.getLayoutParams().width = sCreenWidth
- mMenuRightPadding;
mContent.getLayoutParams().width = sCreenWidth;
once = false;
}
}
/**
* 决定组件在什么位置
*/
@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) {
scrollTo(mMenuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
// 隐藏在左边的宽度
int scrollX = getScrollX();
if (scrollX <= mMenuWidth / 2) {
smoothScrollTo(0, 0);
} else {
smoothScrollTo(mMenuWidth, 0);
}
return true;
default:
break;
}
return super.onTouchEvent(ev);
}
}