Android Custom Realization of Side Slip Menu Effect
- 2021-11-01 04:41:53
- OfStack
This article example for everyone to share the Android custom implementation of the side slip menu specific code, for your reference, the specific content is as follows
Implementation principle: Inheriting ViewGroup controls to be displayed on the interface requires rewriting OnMeature ()
OnLayout (), so when OnLayout () is realized, the menu interface is drawn to the left side of the screen, and the sliding effect can be realized by dynamically changing the distance between the menu interface and the left boundary of scrollXto ().
1. Inherit ViewGroup
2. Event distribution mechanism
3. Status Monitoring
Add two child controls in the main interface
<com.oblivion.ui.SlideMenu xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sliding_menu"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- In SlidingMenu Index in 0 -->
<include layout="@layout/menu" />
<!-- In SlidingMenu Index in 1 -->
<include layout="@layout/main" />
</com.oblivion.ui.SlideMenu>
menu menu layout
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="240dp"
android:layout_height="match_parent"
android:background="@drawable/menu_bg">
<LinearLayout
android:layout_width="240dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_news"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/select_menu"
android:clickable="true"
android:drawableLeft="@drawable/tab_news"
android:drawablePadding="10dp"
android:text=" News " />
<TextView
android:id="@+id/tv_read"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_read"
android:drawablePadding="10dp"
android:text=" Subscribe " />
<TextView
android:id="@+id/tv_local"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_local"
android:drawablePadding="10dp"
android:text=" Local " />
<TextView
android:id="@+id/tv_ties"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_ties"
android:drawablePadding="10dp"
android:text=" Follow-up post " />
<TextView
android:id="@+id/tv_pics"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_pics"
android:drawablePadding="10dp"
android:text=" Picture " />
<TextView
android:id="@+id/tv_ugc"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_ugc"
android:drawablePadding="10dp"
android:text=" Topic " />
<TextView
android:id="@+id/tv_vote"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_vote"
android:drawablePadding="10dp"
android:text=" Vote " />
<TextView
android:id="@+id/tv_focus"
style="@style/menu_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/tab_focus"
android:drawablePadding="10dp"
android:text=" Focus " />
</LinearLayout>
</ScrollView>
Display interface layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/top_bar_bg"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_showmenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/main_back" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@drawable/top_bar_divider"></View>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text=" News front page "
android:textColor="#ffffff"
android:textSize="30sp" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:text=" Fuck, so low"
android:textColor="#000000"
android:textSize="20sp" />
</LinearLayout>
Implementation principle: OnMeature () OnLayout () is needed to be rewritten to display ViewGroup control on the interface. Therefore, when OnLayout () is realized, the menu interface is drawn to the left side of the screen, and the sliding effect can be realized by dynamically changing the distance between the menu interface and the left boundary of scrollXto ().
Implement onMeasure () and onLayout () methods to lay out controls
/**
* Measuring Controls in Layout
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);// Measure its own width and height
// Get menu Interface
menuView = getChildAt(0);
menuViewWidth = menuView.getLayoutParams().width;
// Get main Interface
mainView = getChildAt(1);
// Setting menuView Width of ------ No need setMeasure...
menuView.measure(MeasureSpec.makeMeasureSpec(menuViewWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
// Setting mainView Width of
mainView.measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int menuleft = -menuViewWidth;//menu Set left
int menuright = 0;//menu Set right
int menutop = 0;//menu Set top
int menubottom = b - t;//menu Set bottom
// Layout menuView Control xx2
menuView.layout(menuleft, menutop, menuright, menubottom);
int mainleft = 0;//main Set left
int mainright = r - l;//main Set right
int maintop = 0;//main Set top
int mainbottom = b - t;//main Set bottom
// Layout mainView --------------- Control ..... Your mother forced her way --------- The direction is left,top,right,bottom
mainView.layout(mainleft, maintop, mainright, mainbottom);
System.out.println(menuViewWidth--);// It turns out that this has been reduced here;
}
The boundary value is obtained by onTouch () method, scrollX () and getScrollX () method, and dynamically changed to realize sliding.
Note here that scrollX () and getScrollX () get values relative to the starting point of the layout, so they need to be re-encapsulated;
To smooth animation, it is necessary to create an Scroll class in the constructor, and then judge whether the set smooth animation is over through the ComplentScroll... method.
Finally, through the boundary value after the animation, judge whether it is open or closed.
/**
* Due to the system scrollTo Is a reverse operation, so it needs to be encapsulated 1 Under
*
* @param distance
*/
private void scrollTo(int distance) {
super.scrollTo(-distance, 0);
}
public int getMyScrollX() {
return -getScrollX();
}
/**
* Control touch state
*
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Record the press point
down_dot = (int) event.getX();
System.out.println(down_dot);
break;
case MotionEvent.ACTION_MOVE:
int move_dot = (int) event.getX();
// Absolute value of the distance between dynamic moving points and pressed points
move2down_distance = move_dot - down_dot;
// Move spacing and last lifted point
int lastUp_dot = move2down_distance + up_dot;
// Control boundary
if (lastUp_dot >= menuViewWidth) {
lastUp_dot = menuViewWidth;
} else if (lastUp_dot <= 0) {
lastUp_dot = 0;
}
// Set the distance after moving
scrollTo(lastUp_dot);
break;
case MotionEvent.ACTION_UP:
// Presently lift your finger point
up_dot = (int) event.getX();
// Set the final state
setFinalScroll();
break;
}
return true;// Consumption of Events
}
/**
* When the finger is lifted, record the final state;
*/
private void setFinalScroll() {
// Get the distance from the left boundary of the current distance
currrentScroll = getMyScrollX();
if (currrentScroll >= menuViewWidth / 2) {
//scrollTo(menuViewWidth);
rightAnimation();
} else {
leftAnimation();
}
}
/**
* Smooth moving left animation
*/
private void leftAnimation() {
//scrollTo(0);
int dx = 0 - currrentScroll;// The distance to move
// Set Smooth Animation
msScroller.startScroll(currrentScroll, 0, dx, 0, 300);
invalidate();
// Setting 1 Lower lifting point
up_dot = 0;
// Calling the closed state of the interface
mOnDragStateListener.onDragClose();
}
/**
* Animation that moves smoothly to the right
*/
private void rightAnimation() {
int dx = menuViewWidth - currrentScroll;// The distance to move
// Set Smooth Animation
msScroller.startScroll(currrentScroll, 0, dx, 0, 300);
invalidate();
// Setting 1 Lower lifting point
up_dot = menuViewWidth;
// Invoke the open state of the interface
mOnDragStateListener.onDragOpen();
}
/**
* Does the smooth move animation end
*/
@Override
public void computeScroll() {
super.computeScroll();
if (msScroller.computeScrollOffset()) {
int currX = msScroller.getCurrX();// The simulated value
scrollTo(currX);
invalidate();
}
}
Create listening and callback interfaces
/**
* Drag-and-drop monitoring
*/
public void setOnDragStateListener(onDragStateListener listener) {
mOnDragStateListener = listener;
}
/**
* Callback modification status
*
* @param dragState
*/
public void setStateChange(boolean dragState) {
if (dragState) {
currrentScroll = 0;
rightAnimation();
} else {
currrentScroll = menuViewWidth;
leftAnimation();
}
}
/**
* Create a drag-and-drop callback interface
*/
public interface onDragStateListener {
/**
* Be dragged away
*/
void onDragOpen();
/**
* Be shut down
*/
void onDragClose();
}
Implementation of monitoring effect in main Activity
iv_showmenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// After the picture clicks, it triggers to change the state
sliding_menu.setStateChange(dragState);
}
});
sliding_menu.setOnDragStateListener(new SlideMenu.onDragStateListener() {
@Override
public void onDragOpen() {
ToastUtils.setToast(getApplicationContext(), "open");
dragState = false;
tv_news.setSelected(true);
tv_news.setTextColor(Color.BLUE);
}
@Override
public void onDragClose() {
ToastUtils.setToast(getApplicationContext(), "close");
dragState = true;
tv_news.setSelected(false);
tv_news.setTextColor(Color.WHITE);
}
});
tv_news.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ToastUtils.setToast(getApplicationContext(), tv_news.getText().toString());
}
});
}
github source address