Android Getting Started - Button Control + Custom Button Control

Android Getting Started - Button Control + Custom Button Control

The first step is to drag a Button control into the layout file, of course you can also code it yourself. The XML layout is as follows

  1. <RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android"  
  2. xmlns:tools= "http://schemas.android.com/tools"  
  3. android:layout_width= "match_parent"  
  4. android:layout_height= "match_parent"  
  5.      
  6. >
  7.  
  8. <Button
  9. android:id= "@+id/button1" <!-- The id number of the button. The program uses this id number to find the corresponding control -->
  10. android:layout_width= "wrap_content" <!-- The width of the button. Currently, it means automatically stretching according to the content. Other options include match_parent, which means adjusting the size according to the parent control. -->
  11. android:layout_height= "wrap_content" <!-- button length -->
  12. android:layout_alignParentTop= "true" <!-- In RelativeLayout, align the top edge of the control with the top edge of the parent control -->
  13. android:layout_centerHorizontal= "true" <!-- In RelativeLayout, horizontal centering means -->
  14. android:layout_marginTop= "150dp" <!-- Distance from the top of the parent control in RelativeLayout -->
  15. android:text= "Button" /> <!-- The text information displayed on the button -->
  16.  
  17. </RelativeLayout>

Of course, there are many layout properties of a control, which we need to use more and become familiar with.

Then call it in the program

  1. public   class MainActivity extends Activity {
  2.      
  3. private Button myButton;
  4.  
  5. @Override  
  6. protected   void onCreate(Bundle savedInstanceState) {
  7. super .onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. //Find controls by id. Remember to set the layout file before finding controls.  
  10. myButton = (Button)findViewById(R.id.button1);
  11. myButton.setOnClickListener( new OnClickListener() {
  12.              
  13. @Override  
  14. public   void onClick(View v) {
  15. // TODO Auto-generated method stub  
  16. //Fill in the event to be executed after clicking the button  
  17. }
  18.              
  19. });
  20. myButton.setOnTouchListener( new OnTouchListener(){...}); //Set the listener for touching the button  
  21. myButton.setOnLongClickListener( new OnLongClickListener(){...}); //Set the listener for long pressing the button  
  22. myButton.setOnHoverListener( new OnHoverListener(){...}); //Set the listener when the interface covers the button  
  23. //There are other listeners, we can call the corresponding listeners according to different needs  
  24. }
  25.  
  26.  
  27. }

Or set the listener like this

  1. public   class MainActivity extends Activity implements OnClickListener{
  2.      
  3. private Button myButton;
  4.  
  5. @Override  
  6. protected   void onCreate(Bundle savedInstanceState) {
  7. super .onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. //Find controls. Remember to set the layout file before searching for controls.  
  10. myButton = (Button)findViewById(R.id.button1);
  11. myButton.setOnClickListener( this );
  12.              
  13.  
  14. }
  15.  
  16. @Override  
  17. public   void onClick(View v) {
  18. // TODO Auto-generated method stub  
  19. //Get the clicked View  
  20. switch (v.getId()){
  21. //Perform related operations based on the View id  
  22. case R.id.button1:
  23. //Handle related events when the button is clicked  
  24. break ;
  25. }
  26. }
  27.  
  28.  
  29. }

A button control with basic functions is now complete. But of course, this is not the focus of today's discussion. The focus is on how to customize a button instead of using the button given to us by the system.

2. Custom Buttons

Let’s take a look at the effect picture first.

This is a button with a built-in progress bar, which can display the progress of the asynchronous task and end the operation when it is completed. Let's see how it is implemented.

  1. Split this button. Looking carefully at the effect diagram above, we can divide this button into 3 parts. The first is the simplest outer circle. Basically, just draw a circle and put it there. Then there are the triangle, square and check mark in the middle. We can use the drawing class in the view to outline them, and then use a simple animation to switch. The last part is the circle covering the circle and constantly indicating the progress. We can constantly call the ondraw of this view to refresh the progress. This is the design idea of ​​the whole button. Let's take a look at the actual code.
  2. First, let’s create a circle that represents progress. Let’s create a CusImage-derived view class and pass in progress parameters in real time.
  1. package com.example.mybutton;
  2.  
  3. import android.annotation.SuppressLint;
  4. import android.content.Context;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.graphics.RectF;
  9. import android.util.AttributeSet;
  10. import android.util.DisplayMetrics;
  11. import android.util.Log;
  12. import android.view.View;
  13.  
  14. @SuppressLint ( "ViewConstructor" )
  15. public   class CusImage extends View {
  16.  
  17. private ButtonLayout b;
  18. private Paint myPaint;
  19. private   float startAngle, sweepAngle;
  20. private RectF rect;
  21. //Default control size  
  22. private   int pix = 160 ;
  23.  
  24. public CusImage(Context context, ButtonLayout b) {
  25. super (context);
  26. this .b = b;
  27. init();
  28. // TODO Auto-generated constructor stub  
  29. }
  30.  
  31. public CusImage(Context context, AttributeSet attrs, ButtonLayout b) {
  32. super (context, attrs);
  33. this .b = b;
  34. init();
  35. // TODO Auto-generated constructor stub  
  36. }
  37.  
  38. private   void init() {
  39. myPaint = new Paint();
  40. DisplayMetrics metrics = getContext().getResources()
  41. .getDisplayMetrics();
  42. int width = metrics.widthPixels;
  43. int height = metrics.heightPixels;
  44. Log.d( "TAG" , width + "" );
  45. Log.d( "TAG" , height + "" );
  46. float scarea = width * height;
  47. pix = ( int ) Math.sqrt(scarea * 0.0217 );
  48.  
  49. // Anti-aliasing  
  50. myPaint.setAntiAlias( true );
  51. //stroke means hollow, Fill means solid  
  52. myPaint.setStyle(Paint.Style.STROKE);
  53. //color  
  54. myPaint.setColor(Color.rgb( 0 , 161 , 234 ));
  55. //Set line thickness  
  56. myPaint.setStrokeWidth( 7 );
  57.  
  58. float startx = ( float ) (pix * 0.05 );
  59. float endx = ( float ) (pix * 0.95 );
  60. float starty = ( float ) (pix * 0.05 );
  61. float endy = ( float ) (pix * 0.95 );
  62. //Rectangular area  
  63. rect = new RectF(startx, starty, endx, endy);
  64. }
  65.  
  66. @Override  
  67. protected   void onDraw(Canvas canvas) {
  68. // Draw an arc  
  69. // Draw in the rect area, the starting angle, the degree of sweeping instead of the ending angle, false means not connecting with the center of the circle, true is usually used to draw sectors, brushes.  
  70. canvas.drawArc(rect, startAngle, sweepAngle, false , myPaint);
  71. startAngle = -90 ;
  72.  
  73. //Less than 1 circle  
  74. if (sweepAngle < 360 &&b.flg_frmwrk_mode == 2 ) {
  75. invalidate();
  76. } else   if (b.flg_frmwrk_mode == 1 ){
  77.                      
  78. } else { //After scanning a circle, call b.finalAnimation()  
  79. sweepAngle = 0 ;
  80. startAngle = - 90 ;
  81. b.finalAnimation();
  82.  
  83. }
  84. super .onDraw(canvas);
  85. }
  86.  
  87. /**
  88. * Control the size of the control http://blog.csdn.net/pi9nc/article/details/18764863
  89. **/  
  90. @Override  
  91. protected   void onMeasure( int widthMeasureSpec, int heightMeasureSpec) {
  92. int desiredWidth = pix;
  93. int desiredHeight = pix;
  94. int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  95. int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  96. int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  97. int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  98.  
  99. int width;
  100. int height;
  101.  
  102. // If the control width is the specified size, the width is the specified size  
  103. if (widthMode == MeasureSpec.EXACTLY) {
  104. width = widthSize;
  105. } else   if (widthMode == MeasureSpec.AT_MOST) { // No limit, default content size  
  106. width = Math.min(desiredWidth, widthSize);
  107. } else {
  108. width = desiredWidth;
  109. }
  110.  
  111. // If the control height is the specified size, the height is the specified size  
  112. if (heightMode == MeasureSpec.EXACTLY) {
  113. height = heightSize;
  114. } else   if (heightMode == MeasureSpec.AT_MOST) { // No limit, default content size  
  115. height = Math.min(desiredHeight, heightSize);
  116. } else {
  117. height = desiredHeight;
  118. }
  119. // Set the control size  
  120. setMeasuredDimension(width, height);
  121. }
  122. // Pass in parameters  
  123. public   void setupprogress( int progress) {
  124. sweepAngle = ( float ) (progress * 3.6 );
  125. }
  126.  
  127. public   void reset() {
  128. startAngle = -90 ;
  129. }
  130.  
  131. }

After we have the view that represents the progress, we need to assemble the various parts in a viewgroup control to implement the entire button. Here I use framelayout

The codes are written together here, I will explain them one by one.

First is the initialization of ImageView

  1. /**
  2. * Create each control
  3. */  
  4. private   void initialise() {
  5. //Button progress bar  
  6. cusView = new CusImage(getContext(), this );
  7. // The shape in the middle of the button  
  8. buttonimage = new ImageView(getContext());
  9. // The image displayed after the progress is completed  
  10. fillcircle = new ImageView(getContext());
  11. //A circle outside  
  12. full_circle_image = new ImageView(getContext());
  13. // Set the control to not accept click events  
  14. cusView.setClickable( false );
  15. buttonimage.setClickable( false );
  16. fillcircle.setClickable( false );
  17. full_circle_image.setClickable( false );
  18.  
  19. setClickable( true );
  20.  
  21. }

Then set up the animation

  1. /**
  2. * Set up animation and animation listener
  3. */  
  4. private   void setAnimation() {
  5.  
  6. // Setting up and defining view animations.  
  7.  
  8. // http://blog.csdn.net/congqingbin/article/details/7889778  
  9. // RELATIVE_TO_PARENT: Focus on the center of the parent control; RELATIVE_TO_SELF focuses on itself  
  10. // The upper left corner is 0.0f 0.0f, the center is 0.5f, 0.5f, and the lower right corner is 1.0f, 1.0f  
  11. /*
  12. * arcRotation = new RotateAnimation(0.0f, 360.0f,
  13. * Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
  14. */  
  15. // Duration 1000ms  
  16. // arcRotation.setDuration(500);  
  17.  
  18. in = new AnimationSet( true );
  19. out = new AnimationSet( true );
  20.  
  21. // http://blog.csdn.net/jason0539/article/details/16370405  
  22. out.setInterpolator( new AccelerateDecelerateInterpolator());
  23. in.setInterpolator( new AccelerateDecelerateInterpolator());
  24.  
  25. // http://blog.csdn.net/xsl1990/article/details/17096501  
  26. scale_in = new ScaleAnimation( 0 .0f, 1 .0f, 0 .0f, 1 .0f,
  27. Animation.RELATIVE_TO_SELF, 0.5f , Animation.RELATIVE_TO_SELF,
  28. 0.5f );
  29. scale_out = new ScaleAnimation( 1 .0f, 3 .0f, 1 .0f, 3 .0f,
  30. Animation.RELATIVE_TO_SELF, 0.5f , Animation.RELATIVE_TO_SELF,
  31. 0.5f );
  32.  
  33. // Scaling animation, the initial x-axis scale is 0, the y-axis scale is 0, after the animation, the x and y axis sizes are the same as the image size  
  34. // x,y can be used as width and height  
  35. new_scale_in = new ScaleAnimation( 0 .0f, 1 .0f, 0 .0f, 1 .0f,
  36. Animation.RELATIVE_TO_SELF, 0.5f , Animation.RELATIVE_TO_SELF,
  37. 0.5f );
  38.  
  39. new_scale_in.setDuration( 200 );
  40.  
  41. // Transparency animation  
  42. fade_in = new AlphaAnimation( 0 .0f, 1 .0f);
  43. fade_out = new AlphaAnimation( 1 .0f, 0 .0f);
  44.  
  45. scale_in.setDuration( 150 );
  46. scale_out.setDuration( 150 );
  47. fade_in.setDuration( 150 );
  48. fade_out.setDuration( 150 );
  49.  
  50. // Enter the animation set  
  51. in.addAnimation(scale_in);
  52. in.addAnimation(fade_in);
  53. // Exit animation set  
  54. out.addAnimation(fade_out);
  55. out.addAnimation(scale_out);
  56.  
  57. out.setAnimationListener( new AnimationListener() {
  58.  
  59. @Override  
  60. public   void onAnimationStart(Animation animation) {
  61. // TODO Auto-generated method stub  
  62. System.out.println( "print this" );
  63. }
  64.  
  65. @Override  
  66. public   void onAnimationRepeat(Animation animation) {
  67. // TODO Auto-generated method stub  
  68.  
  69. }
  70.  
  71. @Override  
  72. public   void onAnimationEnd(Animation animation) {
  73. // TODO Auto-generated method stub  
  74.  
  75. buttonimage.setVisibility(View.GONE);
  76. buttonimage.setImageBitmap(second_icon_bmp);
  77. buttonimage.setVisibility(View.VISIBLE);
  78. buttonimage.startAnimation(in);
  79. full_circle_image.setVisibility(View.VISIBLE);
  80. cusView.setVisibility(View.VISIBLE);
  81.  
  82. flg_frmwrk_mode = 2 ;
  83.  
  84. System.out.println( "flg_frmwrk_mode" + flg_frmwrk_mode);
  85.  
  86. }
  87. });
  88.  
  89. new_scale_in.setAnimationListener( new AnimationListener() {
  90.  
  91. @Override  
  92. public   void onAnimationStart(Animation animation) {
  93. // TODO Auto-generated method stub  
  94.  
  95. }
  96.  
  97. @Override  
  98. public   void onAnimationRepeat(Animation animation) {
  99. // TODO Auto-generated method stub  
  100.  
  101. }
  102.  
  103. @Override  
  104. public   void onAnimationEnd(Animation animation) {
  105. // TODO Auto-generated method stub  
  106. cusView.setVisibility(View.GONE);
  107. buttonimage.setVisibility(View.VISIBLE);
  108. buttonimage.setImageBitmap(third_icon_bmp);
  109. flg_frmwrk_mode = 3 ;
  110. buttonimage.startAnimation(in);
  111.  
  112. }
  113. });
  114.  
  115. }

Next, draw the shapes.

  1. * Set the path of each screen
  2. */
  3. private   void iconCreate() {
  4.  
  5. // Creating icons using path  
  6. // Create your own icons or feel free to use these  
  7.  
  8. play = new Path();
  9. play.moveTo(pix * 40 / 100 , pix * 36 / 100 );
  10. play.lineTo(pix * 40 / 100 , pix * 63 / 100 );
  11. play.lineTo(pix * 69 / 100 , pix * 50 / 100 );
  12. play.close();
  13.  
  14. stop = new Path();
  15. stop.moveTo(pix * 38 / 100 , pix * 38 / 100 );
  16. stop.lineTo(pix * 62 / 100 , pix * 38 / 100 );
  17. stop.lineTo(pix * 62 / 100 , pix * 62 / 100 );
  18. stop.lineTo(pix * 38 / 100 , pix * 62 / 100 );
  19. stop.close();
  20.  
  21. download_triangle = new Path();
  22. download_triangle.moveTo(pix * 375 / 1000 , (pix / 2 )
  23. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  24. download_triangle.lineTo(pix / 2 , (pix * 625 / 1000 )
  25. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  26. download_triangle.lineTo(pix * 625 / 1000 , (pix / 2 )
  27. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  28. download_triangle.close();
  29.  
  30. download_rectangle = new Path();
  31. download_rectangle.moveTo(pix * 4375 / 10000 , (pix / 2 )
  32. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  33. download_rectangle.lineTo(pix * 5625 / 10000 , (pix / 2 )
  34. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  35. download_rectangle.lineTo(pix * 5625 / 10000 , (pix * 375 / 1000 )
  36. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  37. download_rectangle.lineTo(pix * 4375 / 10000 , (pix * 375 / 1000 )
  38. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  39. download_rectangle.close();
  40.  
  41. tick = new Path();
  42. tick.moveTo(pix * 30 / 100 , pix * 50 / 100 );
  43. tick.lineTo(pix * 45 / 100 , pix * 625 / 1000 );
  44. tick.lineTo(pix * 65 / 100 , pix * 350 / 1000 );
  45.  
  46. }
  47.  
  48. /**
  49. * Create each bitmap and add it to framelayout
  50. */  
  51. public   void init() {
  52.  
  53. // Defining and drawing bitmaps and assigning views to the layout  
  54.  
  55. FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
  56. FrameLayout.LayoutParams.WRAP_CONTENT,
  57. FrameLayout.LayoutParams.WRAP_CONTENT);
  58.  
  59. lp.setMargins( 10 , 10 , 10 , 10 );
  60.  
  61. fillcircle.setVisibility(View.GONE);
  62.  
  63. Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types  
  64. Bitmap full_circle_bmp = Bitmap.createBitmap(pix, pix, conf);
  65. Bitmap fill_circle_bmp = Bitmap.createBitmap(pix, pix, conf);
  66.  
  67. first_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw  
  68. // first icon(  
  69. //Default -  
  70. // Play )  
  71.  
  72. second_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw  
  73. // second icon(  
  74. //Default -  
  75. // Stop )  
  76.  
  77. third_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw  
  78. // third icon(  
  79. //Default -  
  80. // Tick )  
  81.  
  82. Canvas first_icon_canvas = new Canvas(first_icon_bmp);
  83. Canvas second_icon_canvas = new Canvas(second_icon_bmp);
  84. Canvas third_icon_canvas = new Canvas(third_icon_bmp);
  85. Canvas fill_circle_canvas = new Canvas(fill_circle_bmp);
  86. Canvas full_circle_canvas = new Canvas(full_circle_bmp);
  87. float startx = ( float ) (pix * 0.05 );
  88. float endx = ( float ) (pix * 0.95 );
  89. System.out.println( "full circle " + full_circle_canvas.getWidth()
  90. + full_circle_canvas.getHeight());
  91. float starty = ( float ) (pix * 0.05 );
  92. float endy = ( float ) (pix * 0.95 );
  93. rect = new RectF(startx, starty, endx, endy);
  94.  
  95. first_icon_canvas.drawPath(play, fill_color); // Draw second icon on  
  96. // canvas(Default -  
  97. // Stop ).  
  98. //*****Set your second  
  99. //icon here****  
  100.  
  101. second_icon_canvas.drawPath(stop, icon_color); // Draw second icon on  
  102. // canvas(Default -  
  103. // Stop ).  
  104. //*****Set your second  
  105. //icon here****  
  106.  
  107. third_icon_canvas.drawPath(tick, final_icon_color); // Draw second icon  
  108. // on canvas(  
  109. // Default - Stop ).  
  110. //*****Set your  
  111. // second icon  
  112. //here****  
  113.  
  114. full_circle_canvas.drawArc(rect, 0 , 360 , false , stroke_color);
  115. fill_circle_canvas.drawArc(rect, 0 , 360 , false , fill_color);
  116.  
  117. buttonimage.setImageBitmap(first_icon_bmp);
  118. flg_frmwrk_mode = 1 ;
  119. fillcircle.setImageBitmap(fill_circle_bmp);
  120. full_circle_image.setImageBitmap(full_circle_bmp);
  121.  
  122. cusView.setVisibility(View.GONE);
  123.  
  124. addView(full_circle_image, lp);
  125. addView(fillcircle, lp);
  126. addView(buttonimage, lp);
  127. addView(cusView, lp);
  128.  
  129. }

***With the logical relationship between the state switching when clicking the button, the layout of this button is complete.

Attach the code of the entire class

  1. package com.example.mybutton;
  2.  
  3. import android.content.Context;
  4. import android.graphics.Bitmap;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.graphics.Path;
  9. import android.graphics.RectF;
  10. import android.util.AttributeSet;
  11. import android.util.DisplayMetrics;
  12. import android.view.View;
  13. import android.view.View.OnClickListener;
  14. import android.view.animation.AccelerateDecelerateInterpolator;
  15. import android.view.animation.AlphaAnimation;
  16. import android.view.animation.Animation;
  17. import android.view.animation.AnimationSet;
  18. import android.view.animation.ScaleAnimation;
  19. import android.view.animation.Animation.AnimationListener;
  20. import android.widget.FrameLayout;
  21. import android.widget.ImageView;
  22.  
  23. public   class ButtonLayout extends FrameLayout implements OnClickListener {
  24.  
  25. public CusImage cusView;
  26. public   int pix = 0 ;
  27. public RectF rect;
  28. // Image view  
  29. // The ImageView class can load images from various sources (such as resources or image libraries), calculate the size of the image so that it can be used in other layouts, and provide various display options such as scaling and coloring (rendering).  
  30. private ImageView circle_image, buttonimage, fillcircle, full_circle_image;
  31.  
  32. // You can use it to draw geometric figures, curves, and text based on paths. This is a drawing path class  
  33. private Path stop, tick, play, download_triangle, download_rectangle;
  34.  
  35. // Bitmap class  
  36. private Bitmap third_icon_bmp, second_icon_bmp, first_icon_bmp;
  37.  
  38. //Brush class  
  39. private Paint stroke_color, fill_color, icon_color, final_icon_color;
  40.  
  41. // The AnimationSet class is an animation collection class in the Android system, which is used to control the combination of multiple actions of the View object. This class inherits from the Animation class  
  42. private AnimationSet in, out;
  43.  
  44. // The RotateAnimation class is a rotation animation class in the Android system, which is used to control the rotation of the View object. This class inherits from the Animation class  
  45. // private RotateAnimation arcRotation;  
  46.  
  47. // Zoom animation class  
  48. private ScaleAnimation new_scale_in, scale_in, scale_out;
  49.  
  50. // Transparency animation  
  51. private AlphaAnimation fade_in, fade_out;
  52.  
  53. public   int flg_frmwrk_mode = 0 ;
  54. boolean first_click = false ;
  55.  
  56. public ButtonLayout(Context context, AttributeSet attrs) {
  57. super (context, attrs);
  58. setOnClickListener( this );
  59.  
  60. initialise();
  61. setpaint();
  62. setAnimation();
  63. displayMetrics();
  64. iconCreate();
  65. init();
  66. // TODO Auto-generated constructor stub  
  67. }
  68.  
  69. public ButtonLayout(Context context) {
  70. super (context);
  71. setOnClickListener( this );
  72. setBackgroundColor(Color.CYAN);
  73. initialise();
  74. setpaint();
  75. setAnimation();
  76. displayMetrics();
  77. iconCreate();
  78. init();
  79. }
  80.  
  81. /**
  82. * Create each control
  83. */  
  84. private   void initialise() {
  85. //Button progress bar  
  86. cusView = new CusImage(getContext(), this );
  87. // The shape in the middle of the button  
  88. buttonimage = new ImageView(getContext());
  89. // The image displayed after the progress is completed  
  90. fillcircle = new ImageView(getContext());
  91. //A circle outside  
  92. full_circle_image = new ImageView(getContext());
  93. // Set the control to not accept click events  
  94. cusView.setClickable( false );
  95. buttonimage.setClickable( false );
  96. fillcircle.setClickable( false );
  97. full_circle_image.setClickable( false );
  98.  
  99. setClickable( true );
  100.  
  101. }
  102.  
  103. /**
  104. * Set various brushes
  105. */  
  106. private   void setpaint() {
  107.  
  108. // Setting up color  
  109. // Paint.ANTI_ALIAS_FLAG is the flag to make the bitmap anti-aliased  
  110. stroke_color = new Paint(Paint.ANTI_ALIAS_FLAG);
  111. stroke_color.setAntiAlias( true );
  112. stroke_color.setColor(Color.rgb( 0 , 161 , 234 )); // Edit this to change  
  113. stroke_color.setStrokeWidth( 3 );
  114. stroke_color.setStyle(Paint.Style.STROKE);
  115.  
  116. icon_color = new Paint(Paint.ANTI_ALIAS_FLAG);
  117. icon_color.setColor(Color.rgb( 0 , 161 , 234 ));
  118. // Fill  
  119. icon_color.setStyle(Paint.Style.FILL_AND_STROKE); // Edit this to change  
  120. icon_color.setAntiAlias( true );
  121.  
  122. final_icon_color = new Paint(Paint.ANTI_ALIAS_FLAG);
  123. final_icon_color.setColor(Color.WHITE); // Edit this to change the final  
  124. final_icon_color.setStrokeWidth( 12 );
  125. final_icon_color.setStyle(Paint.Style.STROKE);
  126. final_icon_color.setAntiAlias( true );
  127.  
  128. fill_color = new Paint(Paint.ANTI_ALIAS_FLAG);
  129. fill_color.setColor(Color.rgb( 0 , 161 , 234 )); // Edit this to change the  
  130. fill_color.setStyle(Paint.Style.FILL_AND_STROKE);
  131. fill_color.setAntiAlias( true );
  132.  
  133. }
  134.  
  135. /**
  136. * Set up animation and animation listener
  137. */  
  138. private   void setAnimation() {
  139.  
  140. // Setting up and defining view animations.  
  141.  
  142. // http://blog.csdn.net/congqingbin/article/details/7889778  
  143. // RELATIVE_TO_PARENT: Focus on the center of the parent control; RELATIVE_TO_SELF focuses on itself  
  144. // The upper left corner is 0.0f 0.0f, the center is 0.5f, 0.5f, and the lower right corner is 1.0f, 1.0f  
  145. /*
  146. * arcRotation = new RotateAnimation(0.0f, 360.0f,
  147. * Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
  148. */  
  149. // Duration 1000ms  
  150. // arcRotation.setDuration(500);  
  151.  
  152. in = new AnimationSet( true );
  153. out = new AnimationSet( true );
  154.  
  155. // http://blog.csdn.net/jason0539/article/details/16370405  
  156. out.setInterpolator( new AccelerateDecelerateInterpolator());
  157. in.setInterpolator( new AccelerateDecelerateInterpolator());
  158.  
  159. // http://blog.csdn.net/xsl1990/article/details/17096501  
  160. scale_in = new ScaleAnimation( 0 .0f, 1 .0f, 0 .0f, 1 .0f,
  161. Animation.RELATIVE_TO_SELF, 0.5f , Animation.RELATIVE_TO_SELF,
  162. 0.5f );
  163. scale_out = new ScaleAnimation( 1 .0f, 3 .0f, 1 .0f, 3 .0f,
  164. Animation.RELATIVE_TO_SELF, 0.5f , Animation.RELATIVE_TO_SELF,
  165. 0.5f );
  166.  
  167. // Scaling animation, the initial x-axis scale is 0, the y-axis scale is 0, after the animation, the x and y axis sizes are the same as the image size  
  168. // x,y can be used as width and height  
  169. new_scale_in = new ScaleAnimation( 0 .0f, 1 .0f, 0 .0f, 1 .0f,
  170. Animation.RELATIVE_TO_SELF, 0.5f , Animation.RELATIVE_TO_SELF,
  171. 0.5f );
  172.  
  173. new_scale_in.setDuration( 200 );
  174.  
  175. // Transparency animation  
  176. fade_in = new AlphaAnimation( 0 .0f, 1 .0f);
  177. fade_out = new AlphaAnimation( 1 .0f, 0 .0f);
  178.  
  179. scale_in.setDuration( 150 );
  180. scale_out.setDuration( 150 );
  181. fade_in.setDuration( 150 );
  182. fade_out.setDuration( 150 );
  183.  
  184. // Enter the animation set  
  185. in.addAnimation(scale_in);
  186. in.addAnimation(fade_in);
  187. // Exit animation set  
  188. out.addAnimation(fade_out);
  189. out.addAnimation(scale_out);
  190.  
  191. out.setAnimationListener( new AnimationListener() {
  192.  
  193. @Override  
  194. public   void onAnimationStart(Animation animation) {
  195. // TODO Auto-generated method stub  
  196. System.out.println( "print this" );
  197. }
  198.  
  199. @Override  
  200. public   void onAnimationRepeat(Animation animation) {
  201. // TODO Auto-generated method stub  
  202.  
  203. }
  204.  
  205. @Override  
  206. public   void onAnimationEnd(Animation animation) {
  207. // TODO Auto-generated method stub  
  208.  
  209. buttonimage.setVisibility(View.GONE);
  210. buttonimage.setImageBitmap(second_icon_bmp);
  211. buttonimage.setVisibility(View.VISIBLE);
  212. buttonimage.startAnimation(in);
  213. full_circle_image.setVisibility(View.VISIBLE);
  214. cusView.setVisibility(View.VISIBLE);
  215.  
  216. flg_frmwrk_mode = 2 ;
  217.  
  218. System.out.println( "flg_frmwrk_mode" + flg_frmwrk_mode);
  219.  
  220. }
  221. });
  222.  
  223. new_scale_in.setAnimationListener( new AnimationListener() {
  224.  
  225. @Override  
  226. public   void onAnimationStart(Animation animation) {
  227. // TODO Auto-generated method stub  
  228.  
  229. }
  230.  
  231. @Override  
  232. public   void onAnimationRepeat(Animation animation) {
  233. // TODO Auto-generated method stub  
  234.  
  235. }
  236.  
  237. @Override  
  238. public   void onAnimationEnd(Animation animation) {
  239. // TODO Auto-generated method stub  
  240. cusView.setVisibility(View.GONE);
  241. buttonimage.setVisibility(View.VISIBLE);
  242. buttonimage.setImageBitmap(third_icon_bmp);
  243. flg_frmwrk_mode = 3 ;
  244. buttonimage.startAnimation(in);
  245.  
  246. }
  247. });
  248.  
  249. }
  250.  
  251. /**
  252. * Set the size of the custom control
  253. */  
  254. private   void displayMetrics() {
  255. // Responsible for calculating the size of views and canvas based upon  
  256. // screen resolution.  
  257. DisplayMetrics metrics = getContext().getResources()
  258. .getDisplayMetrics();
  259. int width = metrics.widthPixels;
  260. int height = metrics.heightPixels;
  261. float scarea = width * height;
  262. pix = ( int ) Math.sqrt(scarea * 0.0217 );
  263.  
  264. }
  265.  
  266. /**
  267. * Set the path of each screen
  268. */  
  269. private   void iconCreate() {
  270.  
  271. // Creating icons using path  
  272. // Create your own icons or feel free to use these  
  273.  
  274. play = new Path();
  275. play.moveTo(pix * 40 / 100 , pix * 36 / 100 );
  276. play.lineTo(pix * 40 / 100 , pix * 63 / 100 );
  277. play.lineTo(pix * 69 / 100 , pix * 50 / 100 );
  278. play.close();
  279.  
  280. stop = new Path();
  281. stop.moveTo(pix * 38 / 100 , pix * 38 / 100 );
  282. stop.lineTo(pix * 62 / 100 , pix * 38 / 100 );
  283. stop.lineTo(pix * 62 / 100 , pix * 62 / 100 );
  284. stop.lineTo(pix * 38 / 100 , pix * 62 / 100 );
  285. stop.close();
  286.  
  287. download_triangle = new Path();
  288. download_triangle.moveTo(pix * 375 / 1000 , (pix / 2 )
  289. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  290. download_triangle.lineTo(pix / 2 , (pix * 625 / 1000 )
  291. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  292. download_triangle.lineTo(pix * 625 / 1000 , (pix / 2 )
  293. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  294. download_triangle.close();
  295.  
  296. download_rectangle = new Path();
  297. download_rectangle.moveTo(pix * 4375 / 10000 , (pix / 2 )
  298. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  299. download_rectangle.lineTo(pix * 5625 / 10000 , (pix / 2 )
  300. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  301. download_rectangle.lineTo(pix * 5625 / 10000 , (pix * 375 / 1000 )
  302. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  303. download_rectangle.lineTo(pix * 4375 / 10000 , (pix * 375 / 1000 )
  304. + (pix * 625 / 10000 ) - (pix * 3 / 100 ));
  305. download_rectangle.close();
  306.  
  307. tick = new Path();
  308. tick.moveTo(pix * 30 / 100 , pix * 50 / 100 );
  309. tick.lineTo(pix * 45 / 100 , pix * 625 / 1000 );
  310. tick.lineTo(pix * 65 / 100 , pix * 350 / 1000 );
  311.  
  312. }
  313.  
  314. /**
  315. * Create each bitmap and add it to framelayout
  316. */  
  317. public   void init() {
  318.  
  319. // Defining and drawing bitmaps and assigning views to the layout  
  320.  
  321. FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
  322. FrameLayout.LayoutParams.WRAP_CONTENT,
  323. FrameLayout.LayoutParams.WRAP_CONTENT);
  324.  
  325. lp.setMargins( 10 , 10 , 10 , 10 );
  326.  
  327. fillcircle.setVisibility(View.GONE);
  328.  
  329. Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types  
  330. Bitmap full_circle_bmp = Bitmap.createBitmap(pix, pix, conf);
  331. Bitmap fill_circle_bmp = Bitmap.createBitmap(pix, pix, conf);
  332.  
  333. first_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw  
  334. // first icon(  
  335. //Default -  
  336. // Play )  
  337.  
  338. second_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw  
  339. // second icon(  
  340. // Default -  
  341. // Stop )  
  342.  
  343. third_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw  
  344. // third icon(  
  345. // Default -  
  346. // Tick )  
  347.  
  348. Canvas first_icon_canvas = new Canvas(first_icon_bmp);
  349. Canvas second_icon_canvas = new Canvas(second_icon_bmp);
  350. Canvas third_icon_canvas = new Canvas(third_icon_bmp);
  351. Canvas fill_circle_canvas = new Canvas(fill_circle_bmp);
  352. Canvas full_circle_canvas = new Canvas(full_circle_bmp);
  353. float startx = ( float ) (pix * 0.05 );
  354. float endx = ( float ) (pix * 0.95 );
  355. System.out.println( "full circle " + full_circle_canvas.getWidth()
  356. + full_circle_canvas.getHeight());
  357. float starty = ( float ) (pix * 0.05 );
  358. float endy = ( float ) (pix * 0.95 );
  359. rect = new RectF(startx, starty, endx, endy);
  360.  
  361. first_icon_canvas.drawPath(play, fill_color); // Draw second icon on  
  362. // canvas(Default -  
  363. // Stop ).  
  364. //*****Set your second  
  365. //icon here****  
  366.  
  367. second_icon_canvas.drawPath(stop, icon_color); // Draw second icon on  
  368. // canvas(Default -  
  369. // Stop ).  
  370. //*****Set your second  
  371. //icon here****  
  372.  
  373. third_icon_canvas.drawPath(tick, final_icon_color); // Draw second icon  
  374. // on canvas(  
  375. // Default - Stop ).  
  376. //*****Set your  
  377. // second icon  
  378. //here****  
  379.  
  380. full_circle_canvas.drawArc(rect, 0 , 360 , false , stroke_color);
  381. fill_circle_canvas.drawArc(rect, 0 , 360 , false , fill_color);
  382.  
  383. buttonimage.setImageBitmap(first_icon_bmp);
  384. flg_frmwrk_mode = 1 ;
  385. fillcircle.setImageBitmap(fill_circle_bmp);
  386. full_circle_image.setImageBitmap(full_circle_bmp);
  387.  
  388. cusView.setVisibility(View.GONE);
  389.  
  390. addView(full_circle_image, lp);
  391. addView(fillcircle, lp);
  392. addView(buttonimage, lp);
  393. addView(cusView, lp);
  394.  
  395. }
  396.  
  397. public   void animation() {
  398.  
  399. // Starting view animation and setting flag values  
  400.  
  401. if (flg_frmwrk_mode == 1 ) {
  402. //full_circle_image.setVisibility(View.GONE);  
  403. buttonimage.startAnimation(out);
  404. }
  405.  
  406. }
  407.  
  408. public   void finalAnimation() {
  409.  
  410. // Responsible for final fill up animation  
  411.  
  412. buttonimage.setVisibility(View.GONE);
  413. fillcircle.setVisibility(View.VISIBLE);
  414. fillcircle.startAnimation(new_scale_in);
  415.  
  416. }
  417.  
  418. public   void stop() {
  419.  
  420. // Responsible for resetting the state of view when Stop is clicked  
  421.  
  422. cusView.reset();
  423. buttonimage.setImageBitmap(first_icon_bmp);
  424. flg_frmwrk_mode = 1 ;
  425.  
  426. }
  427.  
  428. @Override  
  429. public   void onClick(View v) {
  430. // TODO Auto-generated method stub  
  431. animation();
  432. }
  433.  
  434. }

Now that the button is ready, we can call it in the Activity

First, write it to the layout file

  1. <RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android"  
  2. xmlns:tools= "http://schemas.android.com/tools"  
  3. android:layout_width= "match_parent"  
  4. android:layout_height= "match_parent"  
  5.      
  6. >
  7.  
  8. <com.example.mybutton.ButtonLayout
  9. android:id= "@+id/ButtonLayout01"  
  10. android:layout_width= "wrap_content"  
  11. android:layout_height= "wrap_content"  
  12. android:layout_centerHorizontal= "true"  
  13. android:layout_centerVertical= "true"  
  14. android:clickable= "true" >
  15. </com.example.mybutton.ButtonLayout>
  16.  
  17. </RelativeLayout>

Then set it in the activity

  1.   public   class MainActivity extends Activity {
  2. 2   
  3. 3       private   static ButtonLayout buttonLayout;
  4. 4   
  5. 5       @Override  
  6. 6       protected   void onCreate(Bundle savedInstanceState) {
  7. 7           super .onCreate(savedInstanceState);
  8. 8 setContentView(R.layout.activity_main);
  9. 9 buttonLayout = (ButtonLayout) findViewById(R.id.ButtonLayout01);
  10. 10 buttonLayout.setOnClickListener( new OnClickListener() {
  11. 11   
  12. 12               @Override  
  13. 13               public   void onClick(View v) {
  14. 14                   // TODO Auto-generated method stub  
  15. 15 buttonLayout.animation(); // Need to call this method for  
  16. 16                   // animation and progression  
  17. 17   
  18. 18                   if (buttonLayout.flg_frmwrk_mode == 1 ) {
  19. 19   
  20. 20                       // Start state. Call any method that you want to execute  
  21. twenty one   
  22. 22 runOnUiThread( new Runnable() {
  23. twenty three   
  24. twenty four                           @Override  
  25. 25                           public   void run() {
  26. 26                               // TODO Auto-generated method stub  
  27. 27 Toast.makeText( MainActivity.this ,
  28. 28                                       "Starting download" , Toast.LENGTH_SHORT)
  29. 29.show ();
  30. 30 }
  31. 31 });
  32. 32                       new DownLoadSigTask().execute();
  33. 33 }
  34. 34                   if (buttonLayout.flg_frmwrk_mode == 2 ) {
  35. 35   
  36. 36                       // Running state. Call any method that you want to execute  
  37. 37   
  38. 38                       new DownLoadSigTask().cancel( true );
  39. 39 buttonLayout.stop();
  40. 40 runOnUiThread( new Runnable() {
  41. 41   
  42. 42                           @Override  
  43. 43                           public   void run() {
  44. 44                               // TODO Auto-generated method stub  
  45. 45 Toast.makeText( MainActivity.this ,
  46. 46                                       "Download stopped" , Toast.LENGTH_SHORT)
  47. 47.show ();
  48. 48 }
  49. 49 });
  50. 50 }
  51. 51                   if (buttonLayout.flg_frmwrk_mode == 3 ) {
  52. 52   
  53. 53                       // End state. Call any method that you want to execute.  
  54. 54   
  55. 55 runOnUiThread( new Runnable() {
  56. 56   
  57. 57                           @Override  
  58. 58                           public   void run() {
  59. 59                               // TODO Auto-generated method stub  
  60. 60 Toast.makeText( MainActivity.this ,
  61. 61                                       "Download complete" , Toast.LENGTH_SHORT)
  62. 62.show ();
  63. 63 }
  64. 64 });
  65. 65 }
  66. 66 }
  67. 67   
  68. 68 });
  69. 69 }
  70. 70   
  71. 71       static   class DownLoadSigTask extends AsyncTask<String, Integer, String> {
  72. 72   
  73. 73           @Override  
  74. 74           protected   void onPreExecute() {
  75. 75   
  76. 76 }
  77. 77   
  78. 78           @Override  
  79. 79           protected String doInBackground( final String... args) {
  80. 80   
  81. 81               // Creating dummy task and updating progress  
  82. 82   
  83. 83               for ( int i = 0 ; i <= 100 ;) {
  84. 84                   try {
  85. 85 Thread.sleep( 50 );
  86. 86   
  87. 87 } catch (InterruptedException e) {
  88. 88   
  89. 89 e.printStackTrace();
  90. 90 }
  91. 91                   if (buttonLayout.flg_frmwrk_mode == 2 &&i<= 100 ){
  92. 92 i++;
  93. 93 publishProgress(i);
  94. 94 }
  95. 95 }
  96. 96   
  97. 97               return   null ;
  98. 98 }
  99. 99   
  100. 100           @Override  
  101. 101           protected   void onProgressUpdate(Integer... progress) {
  102. 102   
  103. 103               // publishing progress to progress arc  
  104. 104   
  105. 105 buttonLayout.cusView.setupprogress(progress[ 0 ]);
  106. 106 }
  107. 107   
  108. 108 }
  109. 109   
  110. 110 }

3. Conclusion

I wrote this button based on an open source project, its address is https://github.com/torryharris/TH-ProgressButton.

I have mixed some URLs in the code. These are the materials I consulted when reading this entire open source code. If you don’t understand it, you can also go to these addresses to check the information.

To be honest, there are too many things to design custom controls, which is not suitable for learning when you are just getting started. However, it is good to have a concept to start with.

In the near future, I will also introduce some of the concepts I encountered today, such as animation, path, and canvas.

So today ends here~

<<:  How to send messages in WeChat Enterprise Account Development

>>:  How to use custom menus in WeChat Enterprise Account Development

Recommend

The new Edge: Much better than IE but still not perfect

Microsoft released Edge browser to replace the bu...

QR code promotion, 6 invalid forms to avoid

When doing new media promotion , many operators d...

It causes about 700 billion in losses every year! We want to reduce this number

Produced by: Science Popularization China Author:...

A Rough Guy - Advanced Chest Training

A rough man-chest training advanced resource intr...

Understand "International Customs Day" in 80 seconds!

I am Dongdong Miao, International Customs Day is ...

A Brief Analysis of Content Distribution Feed Flow

Labs Guide In this era where content is king, all...