第一步:实现类
import com.android.view.tool.Logger;
import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.support.v4.widget.ViewDragHelper.Callback;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/** * DrawerLayout侧滑布局 * * @Project App_View * @Package com.android.view.dragview * @author chenlin * @version 1.0 * @Note TODO */
public class SlideLayout extends ViewGroup {
private static final String TAG = "SlideLayout";
/** 最小距离 */
private static final int MIN_DRAWER_MARGIN = 64;
/** 最小移动速度 */
private static final int MIN_FLING_VELOCITY = 400;
private ViewDragHelper mHelper;
/** 左侧菜单 */
private View mLeftMenuView;
/** 内容视图 */
private View mContentView;
/** 最小移动速度 */
private float minVel;
/** 菜单的偏移量 */
private float mLeftMenuOffset;
private int mMinDrawerMargin;
public SlideLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlideLayout(Context context) {
this(context, null);
}
public SlideLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 得到密度
float density = getResources().getDisplayMetrics().density;
minVel = MIN_FLING_VELOCITY * density;
mMinDrawerMargin = (int) (MIN_DRAWER_MARGIN * density + 0.5f);
// 初始化
mHelper = ViewDragHelper.create(this, 1.0f, cb);
// 从左侧滑入
mHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
// 设置最新速度
mHelper.setMinVelocity(minVel);
}
private Callback cb = new Callback() {
/** * 说明只有mLeftMenuView可以移动 */
@Override
public boolean tryCaptureView(View child, int pointerId) {
Logger.e(TAG, "tryCaptureView");
return child == mLeftMenuView;
}
/** * 触摸到左边时,capture mLeftMenuView */
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
Logger.e(TAG, "onEdgeDragStarted");
mHelper.captureChildView(mLeftMenuView, pointerId);
}
/** * 水平方向移动的距离 */
@Override
public int getViewHorizontalDragRange(View child) {
return child == mLeftMenuView ? child.getWidth() : 0;
}
/** * 菜单移动时,用来设置菜单是否显示 */
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
// 1.先得到菜单的宽度
int childWidth = changedView.getWidth();
// 2.得到偏移量
float offset = (childWidth + left) * 1.0f / childWidth;
// 3.设置是否可见
changedView.setVisibility(offset == 0 ? VISIBLE : GONE);
// 4.
mLeftMenuOffset = offset;
// 5.视图改变了,重绘制
invalidate();
}
/** * 手指放开时 主要用于设定左侧菜单的位置 */
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
// 1.得到宽度
int childWidth = releasedChild.getWidth();
// 2.得到偏移量
float offset = (childWidth + releasedChild.getLeft()) * 1.0f / childWidth;
// 3.设置位置,如果在右边,则菜单移动到0,否则移动到最左侧
int finalLeft = xvel > 0 || xvel == 0 && offset > 0 ? 0 : -childWidth;
mHelper.settleCapturedViewAt(finalLeft, releasedChild.getTop());
}
/** * 计算left 我们的目标范围是-mLeft.getWidth 到 0 的宽度 */
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return Math.max(-child.getWidth(), Math.min(left, 0));
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return super.clampViewPositionVertical(child, top, dy);
}
};
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View leftMenuView = getChildAt(1);
// 1.得到测量的size
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// 2.测量父控件
setMeasuredDimension(widthSize, heightSize);
// 3.先设左菜单
MarginLayoutParams lp = (MarginLayoutParams) leftMenuView.getLayoutParams();
int leftMenuWidthSpec = getChildMeasureSpec(widthMeasureSpec, lp.leftMargin + lp.rightMargin + mMinDrawerMargin, lp.width);
int leftMenuHeighSpec = getChildMeasureSpec(heightMeasureSpec, lp.topMargin + lp.bottomMargin, lp.height);
// 4.测量菜单
leftMenuView.measure(leftMenuWidthSpec, leftMenuHeighSpec);
// 5.右边的内容view
View contentView = getChildAt(0);
lp = (MarginLayoutParams) contentView.getLayoutParams();
int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize - lp.leftMargin - lp.rightMargin, lp.width);
int contentHeightSpec = MeasureSpec.makeMeasureSpec(heightSize - lp.topMargin - lp.bottomMargin, lp.height);
contentView.measure(contentWidthSpec, contentHeightSpec);
// 6.把测量后的view赋值给定义的
mLeftMenuView = leftMenuView;
mContentView = contentView;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 1.先获得子view
View menuView = mLeftMenuView;
View contentView = mContentView;
// 2.进行内容定位
MarginLayoutParams lp = (MarginLayoutParams) contentView.getLayoutParams();
contentView.layout(lp.leftMargin, lp.topMargin, lp.leftMargin + mLeftMenuView.getMeasuredWidth(),
lp.topMargin + mLeftMenuView.getMeasuredHeight());
// 3.菜单定位
lp = (MarginLayoutParams) menuView.getLayoutParams();
final int menuWidth = menuView.getMeasuredWidth();
int left = -menuWidth + (int) (menuWidth * mLeftMenuOffset);
menuView.layout(left, lp.topMargin, left + menuView.getMeasuredWidth(), lp.topMargin + menuView.getMeasuredHeight());
}
/** * 把事件交由mHelper处理 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mHelper.processTouchEvent(ev);
return true;
}
/** * 如果在移动,则不断的绘制 */
@Override
public void computeScroll() {
if (mHelper.continueSettling(true)) {
invalidate();
}
}
/** * 关闭slide */
public void closeSlide() {
View menuView = mLeftMenuView;
mLeftMenuOffset = 0.0f;
mHelper.smoothSlideViewTo(menuView, -menuView.getWidth(), menuView.getTop());
}
/** * 打开slide */
public void openSlide() {
View menuView = mLeftMenuView;
mLeftMenuOffset = 1.0f;
mHelper.smoothSlideViewTo(menuView, 0, menuView.getTop());
}
/** * 设置全屏 */
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
/** * 把布局的参数交由MarginLayoutParam来处理 */
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return new MarginLayoutParams(p);
}
}
第二步:实现类
/** * 实现侧滑效果 * * @Project App_View * @Package com.android.view.dragview * @author chenlin * @version 1.0 * @Date 2016年4月22日 * @Note TODO */
public class SlideActivity extends ActionBarActivity {
private SlideMenuFragment mMenuFragment;
private SlideLayout mSlideLayout;
private TextView mContentTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slide);
initViews();
initFragment();
}
private void initViews() {
mSlideLayout = (SlideLayout) findViewById(R.id.id_drawerlayout);
mContentTv = (TextView) findViewById(R.id.id_content_tv);
}
private void initFragment() {
FragmentManager fm = getSupportFragmentManager();
mMenuFragment = (SlideMenuFragment) fm.findFragmentById(R.id.id_container_menu);
if (mMenuFragment == null) {
mMenuFragment = new SlideMenuFragment();
fm.beginTransaction().add(R.id.id_container_menu, mMenuFragment).commit();
}
mMenuFragment.setOnMenuItemSelectedListener(new SlideMenuFragment.OnMenuItemSelectedListener() {
@Override
public void menuItemSelected(String title) {
mSlideLayout.closeSlide();
mContentTv.setText(title);
}
});
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<com.android.view.dragview.SlideLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/id_drawerlayout" android:layout_width="match_parent" android:layout_height="match_parent" >
<!-- content -->
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#44ff0000" android:clickable="true" >
<TextView android:id="@+id/id_content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="hello world" android:textSize="40sp" />
</RelativeLayout>
<!-- menu -->
<FrameLayout android:id="@+id/id_container_menu" android:layout_width="match_parent" android:layout_height="match_parent" >
</FrameLayout>
</com.android.view.dragview.SlideLayout>
第四步:创建fragment
import com.android.view.R;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
/** * 左侧菜单 * @Project App_View * @Package com.android.view.dragview * @author chenlin * @version 1.0 * @Date 2016年4月22日 * @Note TODO */
public class SlideMenuFragment extends ListFragment {
/**菜单个数*/
private static final int SIZE_MENU_ITEM = 3;
/**菜单集合*/
private SlideMenuItem[] mItems = new SlideMenuItem[SIZE_MENU_ITEM];
private SlideMenuAdapter mAdapter;
//---回调函数----------------------------------------------
public OnMenuItemSelectedListener mlistener;
public interface OnMenuItemSelectedListener {
void menuItemSelected(String title);
}
public void setOnMenuItemSelectedListener(OnMenuItemSelectedListener listener) {
mlistener = listener;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化菜单项
SlideMenuItem menuItem = null;
for (int i = 0; i < mItems.length; i++) {
menuItem = new SlideMenuItem(getResources().getStringArray(R.array.array_left_menu)[i], false, R.drawable.music_36px, R.drawable.music_36px_light);
mItems[i] = menuItem;
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setBackgroundColor(0xffffffff);
//加载数据
mAdapter = new SlideMenuAdapter(getActivity(), mItems);
setListAdapter(mAdapter);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (mlistener != null) {
SlideMenuItem item = (SlideMenuItem) getListAdapter().getItem(position);
mlistener.menuItemSelected(item.text);
}
mAdapter.setSelected(position);
}
}
第四步:创建适配器
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.view.R;
/** * 菜单适配器 * @Project App_View * @Package com.android.view.dragview * @author chenlin * @version 1.0 * @Note TODO */
public class SlideMenuAdapter extends ArrayAdapter<SlideMenuItem> {
private LayoutInflater mInflater;
private int mSelected;
public SlideMenuAdapter(Context context, SlideMenuItem[] objects) {
super(context, -1, objects);
mInflater = LayoutInflater.from(context);
}
public void setSelected(int position) {
this.mSelected = position;
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SlideMenuItem item = getItem(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_left_menu, parent, false);
}
ImageView iv = (ImageView) convertView.findViewById(R.id.id_item_icon);
TextView title = (TextView) convertView.findViewById(R.id.id_item_title);
title.setText(item.text);
iv.setImageResource(item.icon);
convertView.setBackgroundColor(Color.TRANSPARENT);
//如果是选中的
if (position == mSelected) {
iv.setImageResource(item.iconSelected);
convertView.setBackgroundColor(getContext().getResources().getColor(R.color.state_menu_item_selected));
}
return convertView;
}
}
实体类:
/** * 菜单项属性值 * * @Project App_View * @Package com.android.view.dragview * @author chenlin * @version 1.0 * @Note TODO */
public class SlideMenuItem {
public boolean isSelected; //是否选中
public String text;//文本
public int icon;//图标
public int iconSelected;//被选中的图片
public SlideMenuItem(String text, boolean isSelected, int icon, int iconSelected) {
this.text = text;
this.isSelected = isSelected;
this.icon = icon;
this.iconSelected = iconSelected;
}
}
颜色选择器state_menu_item_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@android:color/white"/> <!-- pressed -->
<item android:drawable="@android:color/black"/> <!-- default -->
</selector>
数组文件arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="array_left_menu">
<item>首页</item>
<item>新闻</item>
<item>游戏</item>
</string-array>
</resources>