1.主视图MainUI
MainUI.java
public class MainUI extends RelativeLayout {
private Context context;
private FrameLayout leftMenu,middleMenu,rightMenu,middleMask;
private Scroller mScroller;
public static final int LEFT_ID = 0xaabbcc;
public static final int MIDDLE_ID = 0xaaccbb;
public static final int RIGHT_ID = 0xccbbaa;
public MainUI(Context context) {
super(context);
initView(context);
}
public MainUI(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(Context context) {
this.context = context;
mScroller = new Scroller(context,new DecelerateInterpolator());
leftMenu = new FrameLayout(context);
middleMenu = new FrameLayout(context);
rightMenu = new FrameLayout(context);
middleMask = new FrameLayout(context);
middleMask.setBackgroundColor(0x88000000);
leftMenu.setBackgroundColor(Color.RED);
middleMenu.setBackgroundColor(Color.GREEN);
rightMenu.setBackgroundColor(Color.RED);
leftMenu.setId(LEFT_ID);
middleMenu.setId(MIDDLE_ID);
rightMenu.setId(RIGHT_ID);
addView(leftMenu);
addView(middleMenu);
addView(rightMenu);
addView(middleMask);
middleMask.setAlpha(0);
}
public float onMiddleMask() {
System.out.println("透明度:"+middleMask.getAlpha());
return middleMask.getAlpha();
}
@Override
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
onMiddleMask();
int curX = Math.abs(getScrollX());
float scale = curX/(float)leftMenu.getMeasuredWidth();
middleMask.setAlpha(scale);
}
//测量屏幕高度宽度(widthMeasureSpec, heightMeasureSpec是准确的当前屏幕的宽度和高度)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//设置中间菜单的宽高
middleMenu.measure(widthMeasureSpec,heightMeasureSpec);
middleMask.measure(widthMeasureSpec,heightMeasureSpec);
//获取屏幕最大宽度
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
//计算要设置的宽度
int tempWidthMeasure = MeasureSpec.makeMeasureSpec((int)(maxWidth*0.8),MeasureSpec.EXACTLY);
//设置左右菜单的宽高
leftMenu.measure(tempWidthMeasure,heightMeasureSpec);
rightMenu.measure(tempWidthMeasure,heightMeasureSpec);
}
//填充到屏幕中,并设置他们的位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
middleMenu.layout(l, t, r, b);
middleMask.layout(l, t, r, b);
leftMenu.layout(l-leftMenu.getMeasuredWidth(),t,r,b);
rightMenu.layout(l+middleMenu.getMeasuredWidth(),t
,l+middleMenu.getMeasuredWidth()+rightMenu.getMeasuredWidth(),b);
}
//设置触摸滑动显示菜单
private boolean isTestCompete;
private boolean isLeftRightEvent;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!isTestCompete) {
getEnventType(ev);
return true;
}
if (isLeftRightEvent) {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
int curScrollX = getScrollX();
int dis_x = (int)(ev.getX() - point.x);
int expectx = -dis_x + curScrollX;
int finalX = 0;
if (expectx < 0) {
finalX = Math.max(expectx, -leftMenu.getMeasuredWidth());
}else {
finalX = Math.min(expectx,rightMenu.getMeasuredWidth());
}
scrollTo(finalX,0);
point.x = (int)ev.getX();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
curScrollX = getScrollX();
if (Math.abs(curScrollX) > leftMenu.getMeasuredWidth() >> 1) {
if (curScrollX<0) {
mScroller.startScroll(curScrollX,0,
-leftMenu.getMeasuredWidth()-curScrollX,0);
}else {
mScroller.startScroll(curScrollX,0,
leftMenu.getMeasuredWidth()-curScrollX,0);
}
}else {
mScroller.startScroll(curScrollX,0,-curScrollX,0);
}
invalidate();
isLeftRightEvent = false;
isTestCompete = false;
break;
}
}else {
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_UP:
isLeftRightEvent = false;
isTestCompete = false;
break;
default:
break;
}
}
return super.dispatchTouchEvent(ev);
}
//复写回调方法,不然不会滑动
@Override
public void computeScroll() {
super.computeScroll();
if (!mScroller.computeScrollOffset()) {
return;
}
int tempX = mScroller.getCurrX();
scrollTo(tempX,0);
}
//判断触摸的类型:上下滑动?左右滑动?点击?
private Point point = new Point();//用点来判断是左右滑动还是上下滑动
private static final int TEST_DIS = 20;//用来做比较,如果大于20就视为滑动
private void getEnventType(MotionEvent ev){
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
point.x = (int)ev.getX();
point.y = (int)ev.getY();
//把事件返回给系统处理,不然菜单的点击事件不能执行
super.dispatchTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
//取绝对值Math.abs()
int dx = Math.abs((int)ev.getX() - point.x);
int dy = Math.abs((int)ev.getY() - point.y);
if (dx >= TEST_DIS && dx > dy) {
isLeftRightEvent = true;
isTestCompete = true;
point.x = (int)ev.getX();
point.y = (int)ev.getY();
}else if (dy >= TEST_DIS && dx < dy) {
isLeftRightEvent = false;
isTestCompete = true;
point.x = (int)ev.getX();
point.y = (int)ev.getY();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//把事件返回给系统处理,不然菜单的点击事件不能执行
super.dispatchTouchEvent(ev);
isLeftRightEvent = false;
isTestCompete = false;
break;
}
}
}
2.左右菜单以及中间视图
这里用Frgment实现这三个视图,只贴出左边菜单的代码,其他两个同理
LeftFragment.java
public class LeftFragment extends Fragment {
public LeftFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_left, container, false);
v.findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("hello");
}
});
return v;
}
}
fragment_left.xml
<FrameLayout 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"
tools:context="zs.mainuidemo.LeftFragment">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="按钮" />
</FrameLayout>
3.在Mainctivity中加载MainUI
public class MainActivity extends AppCompatActivity {
private MainUI mainUI;
private LeftFragment leftFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainUI = new MainUI(this);
setContentView(mainUI);
leftFragment = new LeftFragment();
getSupportFragmentManager().beginTransaction().add(MainUI.LEFT_ID,leftFragment).commit();
}
}
效果如下: