Android custom component series [3] -- custom ViewGroup for slide

Source: Internet
Author: User

There are already a lot of articles about custom ViewGroup. Why am I writing this article? For Beginners or friends who are unfamiliar with custom components, I can use it, however, we need to implement and understand the processes and principles step by step to truly break away from other people's Code. However, it is not easy to draw inferences from each other. Many bloggers are not willing to write them step by step, this is very time-consuming, but if it can help readers, I can learn to customize components from this article to achieve my goal.

Step 1: Build a framework to implement a 3/5 and 2/5 split screen interface. The effect is as follows:


The outermost layer is a custom ViewGroup layout file as follows:

Package com. example. testscrollto; import android. content. context; import android. util. attributeSet; import android. view. view; import android. view. viewGroup; import android. view. view. measureSpec; public class MyScrollView extends ViewGroup {private int mWidth; private int mHeight; private float mMenuWeight = 3.0f/5; // ratio of menu interface to private View mMenuView; // menu interface private View mPriView; // content interface public MyScrollView (Cont Ext context, AttributeSet attrs) {super (context, attrs) ;}@ Overrideprotected void onLayout (boolean arg0, int arg1, int arg2, int arg3, int arg4) {System. out. println ("onLayout executed"); mMenuView. layout (0, 0, (int) (mWidth * mMenuWeight), mHeight); mPriView. layout (int) (mWidth * mMenuWeight), 0, mWidth, mHeight);} @ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {System. out. pri Ntln ("onMeasure executed"); super. onMeasure (widthMeasureSpec, heightMeasureSpec);/** the two parameters passed in by onMeasure are the size passed in by the control on the previous layer. In many cases, you need to calculate the actual size of the control when rewriting this method, * Call setMeasuredDimension (int, int) to set the actual size. * The widthMeasureSpec and heightMeasureSpec passed in onMeasure are not general dimensional values, but values that combine the mode and size. * We need to use int mode = MeasureSpec. getMode (widthMeasureSpec) to get the mode. * use int size = MeasureSpec. getSize (widthMeasureSpec) to get the size. * There are three modes: MeasureSpec. UNSPECIFIED, MeasureSpec. EXACTLY, and MeasureSpec. AT_MOST. * MeasureSpec. EXACTLY is the exact size. When we specify the layout_width or layout_height of the control as a specific value, for example, andorid: layout_width = "50dip" or FILL_PARENT, the control size is determined, all are precise dimensions. * MeasureSpec. AT_MOST is the maximum size. When the layout_width or layout_height of the control is set to WRAP_CONTENT, the control Size usually changes with the control's sub-spaces or content, in this case, the widget size must not exceed the maximum size allowed by the parent widget. Therefore, the mode is AT_MOST, and size provides the maximum size allowed by the parent control. * MeasureSpec. UNSPECIFIED is an UNSPECIFIED size. In this case, the parent control is generally AdapterView, which is passed in through the measure method. */MWidth = MeasureSpec. getSize (widthMeasureSpec); // get the width of MyScrollView mHeight = MeasureSpec. getSize (heightMeasureSpec); // get the height of MyScrollView}/** set the right-sliding menu View */public void setMenu (View menu) {mMenuView = menu; addView (mMenuView);}/*** set the main interface View */public void setPrimary (View primary) {mPriView = primary; addView (mPriView );}}
Step 2: Set the interface location as needed

@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {mMenuView.layout(-(int)(mWidth * mMenuWeight), 0, 0, mHeight);mPriView.layout(0, 0, mWidth, mHeight);}

Step 3: Achieve left and right sliding

Package com. example. testscrollto; import android. content. context; import android. util. attributeSet; import android. view. motionEvent; import android. view. view; import android. view. viewGroup; import android. widget. scroller; public class MyScrollView extends ViewGroup {private Context mContext; private int mWidth; private int mHeight; private float mMenuWeight = 3.0f/5; // ratio of the menu interface to private View mMenuView; // pr on the menu interface Ivate View mPriView; // content interface private boolean mIsShowMenu; private Scroller mScroller; public MyScrollView (Context context, AttributeSet attrs) {super (context, attrs); mContext = context; mScroller = new Scroller (mContext) ;}@ Overrideprotected void onLayout (boolean arg0, int arg1, int arg2, int arg3, int arg4) {mMenuView. layout (-(int) (mWidth * mMenuWeight), 0, 0, mHeight); mPriView. layout (0, 0, mWidth, mHe Ight) ;}@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, heightMeasureSpec); mWidth = MeasureSpec. getSize (widthMeasureSpec); // get the width of MyScrollView mHeight = MeasureSpec. getSize (heightMeasureSpec); // get the height of MyScrollView}/** set the right-sliding menu View */public void setMenu (View menu) {mMenuView = menu; addView (mMenuView);}/*** set the main interface View */public void setPrimar Y (View primary) {mPriView = primary; addView (mPriView);} private float mDownX; @ Overridepublic boolean onTouchEvent (MotionEvent event) {float x = event. getX (); switch (event. getAction () {case MotionEvent. ACTION_DOWN: System. out. println ("ACTION_DOWN"); mDownX = x; // record the x coordinate break at press time; case MotionEvent. ACTION_UP: System. out. println ("ACTION_UP"); int dis = (int) (x-mDownX); // The moving distance from if (Math. abs (dis)> (mWidth * MMenuWeight/2) {if (dis> 0) {// if> 0, slide to the right. showMenu ();} else {// If <0, it is sliding hideMenu () ;}} break; default: break;} return true ;}@ Overridepublic void computeScroll () {super. computeScroll (); if (mScroller. computescroloffset () {scrollTo (mScroller. getCurrX (), mScroller. getCurrY (); postInvalidate () ;}} public boolean isShowMenu () {return mIsShowMenu;} public void showMenu () {if (mIsShowMenu) {return;} mIsShowMenu = True; // indicates that int dx = (int) (mWidth * mMenuWeight) has been displayed in the tag menu; // The distance from the slide to the target position. startScroll (getScrollX (), 0,-dx, 0,500); invalidate ();} public void hideMenu () {if (! MIsShowMenu) {return;} mIsShowMenu = false; int dx = (int) (mWidth * mMenuWeight); mScroller. startScroll (getScrollX (), 0, dx, 0,500); invalidate ();}}
From the code above, we can see the following two codes trigger the computeScroll () method.

mScroller.startScroll(getScrollX(), 0, -dx, 0, 500);invalidate();
Step 4: Add a window status switch listener Interface
public interface OnMenuChangedListener{ public void onChanged(boolean isShow);}public void setOnMenuChangedListener(OnMenuChangedListener listener){mListener = listener;}
Modify the showMenu () method and hideMenu () method as follows:

public void showMenu(){ if(mIsShowMenu){ return; } mIsShowMenu = true; int dx = (int)(mWidth * mMenuWeight); mScroller.startScroll(getScrollX(), 0, -dx, 0, 500); if(mListener != null){ mListener.onChanged(mIsShowMenu); } invalidate();}public void hideMenu(){if(!mIsShowMenu){return;}mIsShowMenu = false;int dx = (int)(mWidth * mMenuWeight);mScroller.startScroll(getScrollX(), 0, dx, 0, 500); if(mListener != null){ mListener.onChanged(mIsShowMenu); } invalidate();}
Add a listener to MainActivity

MScrollView. setOnMenuChangedListener (new OnMenuChangedListener () {@ Overridepublic void onChanged (boolean isShow) {System. out. println ("window switched once ");}});
Step 5: implement the menu list and interface based on the specific business and needs (directly paste the code)

MainActivity. java

Package com. example. testrefreshview; import android. app. activity; import android. graphics. color; import android. OS. bundle; import android. view. view; import android. view. view. onClickListener; import android. widget. adapterView; import android. widget. adapterView. onItemClickListener; import android. widget. arrayAdapter; import android. widget. button; import android. widget. listView; import com. example. testrefreshvie W. rightScrollView. preview;/*** test the ViewGroup, RigthScrollView * @ author Lqh */public class MainActivity extends Activity {private RightScrollView mRightScrollView; private Button mShowMenuBtn; private ListView mMenuList; private ArrayAdapter <String> mAdapter; private String [] menus = {"people nearby", "My materials", "Settings", "games", "instant chat "}; @ Overrideprotected void onCreate (Bundle savedInstanceState) {s Uper. onCreate (savedInstanceState); setContentView (R. layout. rightscrollview_test); mRightScrollView = (RightScrollView) findViewById (R. id. rightscrollview); final View menu = getLayoutInflater (). inflate (R. layout. rightscrollview_menu, null); final View primary = getLayoutInflater (). inflate (R. layout. rightscrollview_primary, null); mMenuList = (ListView) menu. findViewById (R. id. list_right_menu); mShowMenuBtn = (Button) primary. findViewById (R. id. btn_showmenu); mAdapter = new ArrayAdapter <String> (this, android. r. layout. simple_list_item_1, menus); mMenuList. setAdapter (mAdapter); mShowMenuBtn. setOnClickListener (new OnClickListener () {public void onClick (View v) {if (mRightScrollView. isShowMenu () {mRightScrollView. hideMenu ();} else {mRightScrollView. showMenu () ;}}); mRightScrollView. setOnMenuChangedListener (new On MenuChangedListener () {public void onChanged (boolean isShow) {if (isShow) {mShowMenuBtn. setText ("Hide menu");} else {mShowMenuBtn. setText ("display menu") ;}}); mRightScrollView. setMenu (menu); mRightScrollView. setPrimary (primary); mMenuList. setOnItemClickListener (new OnItemClickListener () {public void onItemClick (AdapterView <?> Parent, View view, int position, long id) {switch (position) {case 0: primary. setBackgroundColor (Color. CYAN); break; case 1: primary. setBackgroundColor (Color. BLUE); break; case 2: primary. setBackgroundColor (Color. GRAY); break; case 3: primary. setBackgroundColor (Color. MAGENTA); break; case 4: primary. setBackgroundColor (Color. YELLOW); break;} mRightScrollView. hideMenu ();}});}}
RightScrollView. java

Package com. example. testrefreshview; import android. content. context; import android. util. attributeSet; import android. view. motionEvent; import android. view. view; import android. view. viewGroup; import android. widget. scroller;/*** ViewGroup with right sliding menu, similar to Facebook's main interface * @ author Lqh */public class RightScrollView extends ViewGroup {private Context mContext; private Scroller mScroller; private View mMenuView; priva Te View mPriView; private int mWidth; private int mHeight; private boolean mIsShowMenu; private float mMenuWeight = 3.0f/5; private OnMenuChangedListener mListener; public RightScrollView (Context context) {this (context, Context, null);} public RightScrollView (Context context, AttributeSet attrs) {super (context, attrs); mContext = context; mScroller = new Scroller (mContext );} /** set right-sliding menu View */public void setMenu (Vie W menu) {mMenuView = menu; addView (mMenuView);}/*** set the main interface View */public void setPrimary (View primary) {mPriView = primary; addView (mPriView);} public boolean isShowMenu () {return mIsShowMenu;} public void setOnMenuChangedListener (OnMenuChangedListener listener) {mListener = listener;} public void showMenu () {if (mIsShowMenu) {return;} mIsShowMenu = true; int dx = (int) (mWidth * mMenuWeight); mScroller. star TScroll (getScrollX (), 0,-dx, 0,500); if (mListener! = Null) {mListener. onChanged (mIsShowMenu);} invalidate ();} public void hideMenu () {if (! MIsShowMenu) {return;} mIsShowMenu = false; int dx = (int) (mWidth * mMenuWeight); mScroller. startScroll (getScrollX (), 0, dx, 0,500); if (mListener! = Null) {mListener. onChanged (mIsShowMenu);} invalidate ();} private float mDownX; @ Overridepublic boolean onTouchEvent (MotionEvent event) {float x = event. getX (); switch (event. getAction () {case MotionEvent. ACTION_DOWN: mDownX = x; break; case MotionEvent. ACTION_UP: int dis = (int) (x-mDownX); if (Math. abs (dis)> (mWidth * mMenuWeight/2) {if (dis> 0) {showMenu () ;}else {hideMenu () ;}} break ;} return true;} @ Overridepublic void computeScroll () {super. computeScroll (); if (mScroller. computescroloffset () {scrollTo (mScroller. getCurrX (), mScroller. getCurrY (); postInvalidate () ;}@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {mWidth = MeasureSpec. getSize (widthMeasureSpec); mHeight = MeasureSpec. getSize (heightMeasureSpec); setMeasuredDimension (mWidth, mHeight); int widthSpec = MeasureSpec. makeMeasureSpec (int) (mWidth * mMenuWeight), MeasureSpec. EXACTLY); int heightSpec = MeasureSpec. makeMeasureSpec (mHeight, MeasureSpec. EXACTLY); mMenuView. measure (widthSpec, heightSpec); widthSpec = MeasureSpec. makeMeasureSpec (mWidth, MeasureSpec. EXACTLY); mPriView. measure (widthSpec, heightSpec);} @ Overrideprotected void onLayout (boolean changed, int l, int t, int r, int B) {mMenuView. layout (-(int) (mWidth * mMenuWeight), 0, 0, mHeight); mPriView. layout (0, 0, mWidth, mHeight);} public interface OnMenuChangedListener {public void onChanged (boolean isShow );}}
Running effect:



Source code download: http://download.csdn.net/detail/lxq_xsyu/7231677

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.