【Android開發日記】之入門篇(十四)——Button控件+自定義Button控件


    好久不見,又是一個新的學期開始了,為什么我感覺好惆悵啊!這一周也發生了不少事情,節假日放了三天的假(好久沒有這么悠閑過了),實習公司那邊被組長半強制性的要求去解決一個后台登陸的問題,結果就是把Android這塊放在一邊了,滾去看PHP的后台框架了(人家只是一個Android實習生,不帶這么玩的),學校那邊老師布置了一個hibernate的項目,還說我給你們一個月時間,慢慢看,慢慢學習(結果就是在群上發了一大堆的hibernate的視頻教程,還真的是慢慢看慢慢學習了,而且視頻還是極老的,hibernate還是版本3),遇到這種老師我也是醉了。順便求點hibernate的教程,簡單易上手最好了。〈(_ _)〉

    好了,進入正題吧,今天要做的是button這個控件。按鈕在窗口應用程序中是最常見的控件了,也算是程序與用戶進行交互的常見手段了。按鈕觸發的事件處理,我們稱為Evenr Handler,而在Android中,按鈕事件是由系統的Button.OnClickListener所控制。那么接下來先看看最基本的button控件是怎么實現的。

 

一、基本Button控件

  1. 首先第一步就是往布局文件里拖一個Button控件,當然自己碼出來也可以。XML布局如下
    <RelativeLayout 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"
        
         >
    
        <Button
            android:id="@+id/button1"             <!-- button按鈕的id號,程序通過這個id號來查找相應的控件 -->
            android:layout_width="wrap_content"   <!-- button按鈕的寬度 當前意思是 根據內容自動拉伸,其他的還有match_parent,表示根據父控件來調整大小-->
            android:layout_height="wrap_content"  <!-- button按鈕的長度-->
            android:layout_alignParentTop="true"  <!-- RelativeLayout布局中,將控件的上邊緣和父控件的上邊緣對齊 -->
            android:layout_centerHorizontal="true"<!-- RelativeLayout布局中,水平居中的意思 -->
            android:layout_marginTop="150dp"      <!-- RelativeLayout布局中,距離父控件頂端的距離 -->
            android:text="Button" />              <!-- button按鈕上顯示的文字信息 -->
    
    </RelativeLayout>

    當然,一個控件的布局屬性還有很多,這些都是需要我們多用多熟悉才行。

  2. 然后再在程序中調用它
    public class MainActivity extends Activity {
        
        private Button myButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //通過id尋找控件,記得尋找控件前一定要先設置好布局文件
            myButton = (Button)findViewById(R.id.button1);
            myButton.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    //這里填寫單擊按鈕后要執行的事件
                }
                
            });
            myButton.setOnTouchListener(new OnTouchListener(){...});//設置觸碰到按鈕的監聽器
            myButton.setOnLongClickListener(new OnLongClickListener(){...});//設置長按按鈕的監聽器
            myButton.setOnHoverListener(new OnHoverListener(){...});//設置界面覆蓋按鈕時的監聽器
            //還有其它的的監聽器,我們可以根據不同的需求來調用相應的監聽器
        }
    
    
    }

    或者這樣設置監聽器

    public class MainActivity extends Activity implements OnClickListener{
        
        private Button myButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //尋找控件,記得尋找控件前一定要先設置好布局文件
            myButton = (Button)findViewById(R.id.button1);
            myButton.setOnClickListener(this);
                
    
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //獲取點擊的View
            switch(v.getId()){
            //根據View的id來進行相關操作
            case R.id.button1:
                //按鈕點擊時處理相關的事件
                break;
            }
        }
    
    
    }

    這樣一個基礎功能的button控件就完成了。但當然,這不是我們今天要講的重點,重點是我們如何自定義一個按鈕,而不是使用系統給我們的按鈕。

二、自定義按鈕

我們先來看看效果圖吧

 

這是一個自帶進度條的按鈕,它可以顯示異步任務的進度,當完成后結束操作。我們來看看具體是怎么實現的吧。

  1. 拆分這個按鈕。仔細觀察上面的效果圖,我們可以把這個按鈕分成3個部分,首先是最簡單的外面一圈圓,基本上畫出個圓放在那里就行了。接着是中間的三角形,正方形以及完成的勾,這個我們可以使用view里的畫圖類勾勒出來,再使用簡單的動畫Animation來切換。最后的一部分是覆蓋在圓圈上的不斷在表示進度的圓圈,這個我們可以不斷調用這個view的ondraw來刷新進度。這就是整個按鈕的設計思路。我們來看看實際的代碼吧。
  2. 首先是表示進度的圓圈,我們來新建一個CusImage繼承view類,實時的傳入進度參數。
    package com.example.mybutton;
    
    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.util.Log;
    import android.view.View;
    
    @SuppressLint("ViewConstructor") 
    public class CusImage extends View {
    
        private ButtonLayout b;
        private Paint myPaint;
        private float startAngle, sweepAngle;
        private RectF rect;
        // 默認控件大小
        private int pix = 160;
    
        public CusImage(Context context, ButtonLayout b) {
            super(context);
            this.b = b;
            init();
            // TODO Auto-generated constructor stub
        }
    
        public CusImage(Context context, AttributeSet attrs, ButtonLayout b) {
            super(context, attrs);
            this.b = b;
            init();
            // TODO Auto-generated constructor stub
        }
    
        private void init() {
            myPaint = new Paint();
            DisplayMetrics metrics = getContext().getResources()
                    .getDisplayMetrics();
            int width = metrics.widthPixels;
            int height = metrics.heightPixels;
            Log.d("TAG", width + "");
            Log.d("TAG", height + "");
            float scarea = width * height;
            pix = (int) Math.sqrt(scarea * 0.0217);
    
            //抗鋸齒
            myPaint.setAntiAlias(true);
            //stroke表示空心,Fill表示實心
            myPaint.setStyle(Paint.Style.STROKE);
            //顏色
            myPaint.setColor(Color.rgb(0, 161, 234));
            //設置線條粗細
            myPaint.setStrokeWidth(7);
    
            float startx = (float) (pix * 0.05);
            float endx = (float) (pix * 0.95);
            float starty = (float) (pix * 0.05);
            float endy = (float) (pix * 0.95);
            //矩形區域
            rect = new RectF(startx, starty, endx, endy);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            // 畫弧線
            // 在rect這個區域內畫,開始的角度,掃過的度數而不是結束的角度,false表示不與圓心連線,true通常用來畫扇形,畫筆。
            canvas.drawArc(rect, startAngle, sweepAngle, false, myPaint);
            startAngle = -90;
    
            //小於1圈
            if (sweepAngle < 360 &&b.flg_frmwrk_mode == 2) {
                invalidate();
            }else if(b.flg_frmwrk_mode == 1){
                        
            }else {//掃完一圈,調用b.finalAnimation()
                sweepAngle = 0;
                startAngle = -90;
                b.finalAnimation();
    
            }
            super.onDraw(canvas);
        }
    
        /**
         * 控制控件的大小 http://blog.csdn.net/pi9nc/article/details/18764863
         **/
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int desiredWidth = pix;
            int desiredHeight = pix;
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
            int width;
            int height;
    
            // 如果控件寬度是指定大小,寬度為指定的尺寸
            if (widthMode == MeasureSpec.EXACTLY) {
                width = widthSize;
            } else if (widthMode == MeasureSpec.AT_MOST) { // 沒有限制,默認內容大小
                width = Math.min(desiredWidth, widthSize);
            } else {
                width = desiredWidth;
            }
    
            // 如果控件高度是指定大小,高度為指定的尺寸
            if (heightMode == MeasureSpec.EXACTLY) {
                height = heightSize;
            } else if (heightMode == MeasureSpec.AT_MOST) {// 沒有限制,默認內容大小
                height = Math.min(desiredHeight, heightSize);
            } else {
                height = desiredHeight;
            }
            // 設定控件大小
            setMeasuredDimension(width, height);
        }
        // 傳入參數
        public void setupprogress(int progress) {
            sweepAngle = (float) (progress * 3.6);
        }
    
        public void reset() {
            startAngle = -90;
        }
    
    }

     

  3. 有了表示進度的view之后,我們要在一個viewgroup控件中組裝各個部分來實現整個按鈕,這里我用的是framelayout
    這里代碼寫在一起了,我把它們一個一個拎出來講解。
    首先是ImageView的初始化
    /**
         * 創建各個控件
         */
        private void initialise() {
            // 按鈕的進度條
            cusView = new CusImage(getContext(), this);
            // 按鈕中間的形狀
            buttonimage = new ImageView(getContext());
            // 完成進度后顯示的圖像
            fillcircle = new ImageView(getContext());
            //外面一圈圓
            full_circle_image = new ImageView(getContext());
            // 設置控件不接受點擊事件
            cusView.setClickable(false);
            buttonimage.setClickable(false);
            fillcircle.setClickable(false);
            full_circle_image.setClickable(false);
    
            setClickable(true);
    
        }

    然后是設置動畫

    /**
         * 設置動畫及動畫監聽器
         */
        private void setAnimation() {
    
            // Setting up and defining view animations.
    
            // http://blog.csdn.net/congqingbin/article/details/7889778
            // RELATIVE_TO_PARENT:與父控件的的中心為重點;RELATIVE_TO_SELF以自己為中心
            // 左上角 分別為0.0f 0.0f 中心點為0.5f,0.5f 右下角1.0f,1.0f
            /*
             * arcRotation = new RotateAnimation(0.0f, 360.0f,
             * Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
             */
            // 持續時間1000ms
            // arcRotation.setDuration(500);
    
            in = new AnimationSet(true);
            out = new AnimationSet(true);
    
            // http://blog.csdn.net/jason0539/article/details/16370405
            out.setInterpolator(new AccelerateDecelerateInterpolator());
            in.setInterpolator(new AccelerateDecelerateInterpolator());
    
            // http://blog.csdn.net/xsl1990/article/details/17096501
            scale_in = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                    0.5f);
            scale_out = new ScaleAnimation(1.0f, 3.0f, 1.0f, 3.0f,
                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                    0.5f);
    
            // 縮放動畫,起始x軸的縮放為0,y軸的縮放為0,動畫后,x,y軸大小與圖像尺寸相同
            // x,y可以把它當做寬度和高度
            new_scale_in = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
                    Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                    0.5f);
    
            new_scale_in.setDuration(200);
    
            // 透明度的動畫
            fade_in = new AlphaAnimation(0.0f, 1.0f);
            fade_out = new AlphaAnimation(1.0f, 0.0f);
    
            scale_in.setDuration(150);
            scale_out.setDuration(150);
            fade_in.setDuration(150);
            fade_out.setDuration(150);
    
            // 進入的動畫集
            in.addAnimation(scale_in);
            in.addAnimation(fade_in);
            // 退出的動畫集
            out.addAnimation(fade_out);
            out.addAnimation(scale_out);
    
            out.setAnimationListener(new AnimationListener() {
    
                @Override
                public void onAnimationStart(Animation animation) {
                    // TODO Auto-generated method stub
                    System.out.println("print this");
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
                    // TODO Auto-generated method stub
    
                    buttonimage.setVisibility(View.GONE);
                    buttonimage.setImageBitmap(second_icon_bmp);
                    buttonimage.setVisibility(View.VISIBLE);
                    buttonimage.startAnimation(in);
                    full_circle_image.setVisibility(View.VISIBLE);
                    cusView.setVisibility(View.VISIBLE);
    
                    flg_frmwrk_mode = 2;
    
                    System.out.println("flg_frmwrk_mode" + flg_frmwrk_mode);
    
                }
            });
    
            new_scale_in.setAnimationListener(new AnimationListener() {
    
                @Override
                public void onAnimationStart(Animation animation) {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
                    // TODO Auto-generated method stub
                    cusView.setVisibility(View.GONE);
                    buttonimage.setVisibility(View.VISIBLE);
                    buttonimage.setImageBitmap(third_icon_bmp);
                    flg_frmwrk_mode = 3;
                    buttonimage.startAnimation(in);
    
                }
            });
    
        }

    再接着是畫出各個形狀

    /**
         * 設置各個畫面的路徑
         */
        private void iconCreate() {
    
            // Creating icons using path
            // Create your own icons or feel free to use these
    
            play = new Path();
            play.moveTo(pix * 40 / 100, pix * 36 / 100);
            play.lineTo(pix * 40 / 100, pix * 63 / 100);
            play.lineTo(pix * 69 / 100, pix * 50 / 100);
            play.close();
    
            stop = new Path();
            stop.moveTo(pix * 38 / 100, pix * 38 / 100);
            stop.lineTo(pix * 62 / 100, pix * 38 / 100);
            stop.lineTo(pix * 62 / 100, pix * 62 / 100);
            stop.lineTo(pix * 38 / 100, pix * 62 / 100);
            stop.close();
    
            download_triangle = new Path();
            download_triangle.moveTo(pix * 375 / 1000, (pix / 2)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_triangle.lineTo(pix / 2, (pix * 625 / 1000)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_triangle.lineTo(pix * 625 / 1000, (pix / 2)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_triangle.close();
    
            download_rectangle = new Path();
            download_rectangle.moveTo(pix * 4375 / 10000, (pix / 2)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_rectangle.lineTo(pix * 5625 / 10000, (pix / 2)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_rectangle.lineTo(pix * 5625 / 10000, (pix * 375 / 1000)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_rectangle.lineTo(pix * 4375 / 10000, (pix * 375 / 1000)
                    + (pix * 625 / 10000) - (pix * 3 / 100));
            download_rectangle.close();
    
            tick = new Path();
            tick.moveTo(pix * 30 / 100, pix * 50 / 100);
            tick.lineTo(pix * 45 / 100, pix * 625 / 1000);
            tick.lineTo(pix * 65 / 100, pix * 350 / 1000);
    
        }
    
        /**
         * 創建各個bitmap添加到framelayout中
         */
        public void init() {
    
            // Defining and drawing bitmaps and assigning views to the layout
    
            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT);
    
            lp.setMargins(10, 10, 10, 10);
    
            fillcircle.setVisibility(View.GONE);
    
            Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
            Bitmap full_circle_bmp = Bitmap.createBitmap(pix, pix, conf);
            Bitmap fill_circle_bmp = Bitmap.createBitmap(pix, pix, conf);
    
            first_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw
                                                                    // first icon(
                                                                    // Default -
                                                                    // Play )
    
            second_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw
                                                                    // second icon(
                                                                    // Default -
                                                                    // Stop )
    
            third_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw
                                                                    // third icon(
                                                                    // Default -
                                                                    // Tick )
    
            Canvas first_icon_canvas = new Canvas(first_icon_bmp);
            Canvas second_icon_canvas = new Canvas(second_icon_bmp);
            Canvas third_icon_canvas = new Canvas(third_icon_bmp);
            Canvas fill_circle_canvas = new Canvas(fill_circle_bmp);
            Canvas full_circle_canvas = new Canvas(full_circle_bmp);
            float startx = (float) (pix * 0.05);
            float endx = (float) (pix * 0.95);
            System.out.println("full circle " + full_circle_canvas.getWidth()
                    + full_circle_canvas.getHeight());
            float starty = (float) (pix * 0.05);
            float endy = (float) (pix * 0.95);
            rect = new RectF(startx, starty, endx, endy);
    
            first_icon_canvas.drawPath(play, fill_color); // Draw second icon on
                                                            // canvas( Default -
                                                            // Stop ).
                                                            // *****Set your second
                                                            // icon here****
    
            second_icon_canvas.drawPath(stop, icon_color); // Draw second icon on
                                                            // canvas( Default -
                                                            // Stop ).
                                                            // *****Set your second
                                                            // icon here****
    
            third_icon_canvas.drawPath(tick, final_icon_color); // Draw second icon
                                                                // on canvas(
                                                                // Default - Stop ).
                                                                // *****Set your
                                                                // second icon
                                                                // here****
    
            full_circle_canvas.drawArc(rect, 0, 360, false, stroke_color);
            fill_circle_canvas.drawArc(rect, 0, 360, false, fill_color);
    
            buttonimage.setImageBitmap(first_icon_bmp);
            flg_frmwrk_mode = 1;
            fillcircle.setImageBitmap(fill_circle_bmp);
            full_circle_image.setImageBitmap(full_circle_bmp);
    
            cusView.setVisibility(View.GONE);
    
            addView(full_circle_image, lp);
            addView(fillcircle, lp);
            addView(buttonimage, lp);
            addView(cusView, lp);
    
        }

    最后加上點擊按鈕時各個狀態切換的邏輯關系,這個按鈕的布局就完成了。
    附上整個類的代碼

      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     // 圖像視圖
     29     // ImageView類可以加載各種來源的圖片(如資源或圖片庫),需要計算圖像的尺寸,比便它可以在其他布局中使用,並提供例如縮放和着色(渲染)各種顯示選項。
     30     private ImageView circle_image, buttonimage, fillcircle, full_circle_image;
     31 
     32     // 可以用他來畫幾何圖形、畫曲線、畫基於路徑的文本。這是個繪圖的路徑類
     33     private Path stop, tick, play, download_triangle, download_rectangle;
     34 
     35     // 位圖類
     36     private Bitmap third_icon_bmp, second_icon_bmp, first_icon_bmp;
     37 
     38     // 畫筆類
     39     private Paint stroke_color, fill_color, icon_color, final_icon_color;
     40 
     41     // AnimationSet類是Android系統中的動畫集合類,用於控制View對象進行多個動作的組合,該類繼承於Animation類
     42     private AnimationSet in, out;
     43 
     44     // RotateAnimation類是Android系統中的旋轉變化動畫類,用於控制View對象的旋轉動作,該類繼承於Animation類
     45     // private RotateAnimation arcRotation;
     46 
     47     // 縮放動畫類
     48     private ScaleAnimation new_scale_in, scale_in, scale_out;
     49 
     50     // 透明度動畫
     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      * 創建各個控件
     83      */
     84     private void initialise() {
     85         // 按鈕的進度條
     86         cusView = new CusImage(getContext(), this);
     87         // 按鈕中間的形狀
     88         buttonimage = new ImageView(getContext());
     89         // 完成進度后顯示的圖像
     90         fillcircle = new ImageView(getContext());
     91         //外面一圈圓
     92         full_circle_image = new ImageView(getContext());
     93         // 設置控件不接受點擊事件
     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      * 設置各類畫筆
    105      */
    106     private void setpaint() {
    107 
    108         // Setting up color
    109         // Paint.ANTI_ALIAS_FLAG是使位圖抗鋸齒的標志
    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         // 填充
    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      * 設置動畫及動畫監聽器
    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:與父控件的的中心為重點;RELATIVE_TO_SELF以自己為中心
    144         // 左上角 分別為0.0f 0.0f 中心點為0.5f,0.5f 右下角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         // 持續時間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         // 縮放動畫,起始x軸的縮放為0,y軸的縮放為0,動畫后,x,y軸大小與圖像尺寸相同
    168         // x,y可以把它當做寬度和高度
    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         // 透明度的動畫
    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         // 進入的動畫集
    185         in.addAnimation(scale_in);
    186         in.addAnimation(fade_in);
    187         // 退出的動畫集
    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      * 設置自定義控件的大小
    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      * 設置各個畫面的路徑
    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      * 創建各個bitmap添加到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 }
    View Code
  4. 按鈕做好了我們可以在Activity中調用它了
    首先是寫入到布局文件中

    <RelativeLayout 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"
        
         >
    
        <com.example.mybutton.ButtonLayout
            android:id="@+id/ButtonLayout01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:clickable="true" >
        </com.example.mybutton.ButtonLayout>
    
    </RelativeLayout>


    然后在activity中設置

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

     

 

三、結束語

這個按鈕我是仿照一個開源項目寫的,它的地址是https://github.com/torryharris/TH-ProgressButton。

我在代碼中摻雜了一些網址,這些都是我在看這整個開源代碼時查閱的資料,如果你也不懂的話也可以去這些地址看看資料。

說實話,自定義控件設計的東西太多,不適合在入門的時候學習,不過有個概念,以此來拋磚引玉也是挺好的。

接下來不久的時間內我也會把今天遇到的一些概念,比如說animation,path,canvas一一介紹下來的。

那么今天到此結束~

 

========================================

 

作者:cpacm
出處:(http://www.cpacm.net/2015/04/01/Android開發日記(十一)——Button控件-自定義Button控件/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM