Button的創建、監聽與繼承

簡介

 Button繼承自TextView。Button提供的基本響應有:單擊(Click)長按(LongClick)。可以通過觸摸事件管理實現自定義響應,例如雙擊、滑動等。

Button的創建

使用XML佈局創建

 使用XML佈局創建Button的核心在於XML佈局文件findviewById()方法。
activity_main.xml

<LinearLayout ...>
    <Button
        android:id="@+id/btn_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android_background="#50ff00ff"
        android:text="Button1"
        android:gravity="center"
        android:textAllCaps="false"
        android:clickable="true"/>
</LinearLayout>

MainActivity.java

import...
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_1=(Button)findviewById(R.id.btn_1);
    }
}

 代碼中使用findviewById()方法創建了一個名爲btn_1的Button對象。可以使用此對象的各種方法爲按鈕設置監聽器(例如btn_1.setOnClickListener(this));改變按鈕的背景、文字、位置等(例如btn_1.setBackgroundColor(0x50ff00ff))。
 使用findviewById()注意進行強制類型轉換。

使用Java代碼創建

 使用Java代碼可以動態地創建Button。可以使用Java代碼在.xml文件已有的ViewGroup中創建Button;也可以使用Java代碼創建一個新的ViewGroup,將Button添加至新的ViewGroup中。

在.xml文件已有的ViewGroup中添加Button:

步驟:
 ①爲.xml文件中的目標ViewGroup添加android:id屬性。

<LinearLayout
    android:id="@+id/linearlayout_1"
    ...>
    ...
</LinearLayout>

 ②使用findviewById()獲得目標ViewGroup對象。注意進行強制類型轉換。

LinearLayout linearlayout_1=
         (LinearLayout)findviewById(R.id.linearlayout_1);

 ③使用構造函數Button(Context context)創建Button對象。由於WidthHeight等是View的必須屬性,需要先使用ViewGroup.LayoutParams創建佈局參數對象,再使用setLayoutParams()方法爲Button設置WidthHeight等必須屬性。例如:

Button btn_1=new Button(this);
LinearLayout.LayoutParams params_btn =
        new LinearLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT);
        params_btn.topMargin=200;
        params_btn.bottomMargin=200;
btn_1.setLayoutParams(params_btn);        

 ④使用addView()方法向目標ViewGroup中添加Button

linearlayout_1.addView(btn_1);

 對於LinearLayout而言,最先被addView(View v)方法添加到ViewGroup的View擺放在最上面,也就是View的拜訪順序遵循View的添加順序。
 ⑤設置Button的外觀。到這一步,可以使用Button對象的各種方法爲按鈕設置監聽器、改變外觀等。

btn_1.setText("Button1");
btn_1.setBackgroundColor(0x50ff00ff);
btn_1.setOnClickListener(this);

 ⑥爲Button設置id。使用Java代碼爲新創建的Button設置id,需要在res/values/路徑下創建一個Values resourcexml資源文件,並創建id值。使用R.id.name引用id值。例:

<resources>
    <item name="btn_1" type="id"/>
    <item name="btn_2" type="id"/>
</resources>

 使用Button對象的setId(int id)方法設置id。例:

btn_1.setId(R.id.btn_1);

 ⑦移除Button。可以使用ViewGroup對象中的removeView(View view)方法動態地移除指定View,也可以使用removeAllViews()方法移除ViewGroup中的所有View。例:

linearlayout_1.removeView(btn_1);
linearlayout_1.removeAllViews();

完整代碼:
button_id.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="btn_1" type="id"/>
    <item name="btn_2" type="id"/>
</resources>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    
    android:id="@+id/linearlayout_1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="linearlayout_2"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_margin="20dp"/>
        
</LinearLayout>

MainActivity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //find ViewGroup in activity_main.xml
        LinearLayout linearlayout_1=
        (LinearLayout)findviewById(R.id.linearlayout_1);
        LinearLayout linearlayout_2=
        (LinearLayout)findviewById(R.id.linearlayout_2);
        
        //create new buttons
        Button btn_1=new Button(this);
        Button btn_2=new Button(this);
        LinearLayout.LayoutParams params_btn=
                new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        params_btn.topMargin=200;
        params_btn.bottomMargin=200;
        btn_1.setLayoutParams(params_btn);
        btn_2.setLayoutParams(params_btn);
        
        //add button to ViewGroup
        linearlayout_1.addView(btn_1);
        linearlayout_2.addView(btn_2);
        
        //set button's look
        btn_1.setId(R.id.btn_1);
        btn_1.setText("Button1");
        btn_1.setBackgroundColor(0x50ff00ff);
        
        btn_2.setId(R.id.btn_2);
        btn_2.setText("Button2");
        btn_2.setBackgroundColor(0x5000ffff);
    }
}

動態創建ViewGroup並添加Button:

 動態創建ViewGroup的方法與動態創建Button同理,例如:

LinearLayout linearlayout_1=new LinearLayout(this);
LinearLayout.LayoutParams params=
             new LinearLayout.LayoutParams(
             ViewGroup.LayoutParams.MATCH_PARENT,
             ViewGroup.LayoutParams.MATCH_PARENT);
linearlayout_1.setLayoutParams(params);

 使用ViewGroup對象的addView(View view)方法向父ViewGroup中添加新創建的子ViewGroup。例:

linearlayout_main.addView(linearlayout_1);

 使用ViewGroup對象的addView(View view)方法向新創建的子ViewGroup中添加Button。例:

linearlayout_1.addView(btn_1);

完整代碼:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    
    android:id="@+id/linearlayout_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
</LinearLayout>    

MainActivity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //find ViewGroup in activity_main.xml
        LinearLayout linearlayout_main=
            (LinearLayout)findviewById(R.id.linearlayout_main);
        
        //create a new ViewGroup    
        LinearLayout linearlayout_1=new LinearLayout(this);
        LinearLayout.LayoutParams params=
                      new LinearLayout.LayoutParams( 
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
                params.topMargin=200;
        linearlayout_1.setLayoutParams(params);
        
        Button btn_1=new Button(this);
        Button btn_2=new Button(this);
        
        LinearLayout.LayoutParams params_btn=
                      new LinearLayout.LayoutParams( 
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        btn_1.setLayoutParams(params_btn);
        btn_1.setText("Button1);
        btn_2.setLayoutParams(params_btn);  
        btn_1.setText("Button2);
        
        //add views
        linearlayout_main.addView(btn_1);
        linearlayout_main.addView(linearlayout_1);
        linearlayout_1.addView(btn_2);                                 
    }
}

Button的監聽

View.OnClickListener

View.OnClickListener是按鈕點擊監聽器。充當OnClickListener的對象類需要實現View.OnClickListener接口並重寫onClick()方法。例:

public class MyCLickListener implements View.OnClickListener {
    ...
    @Override
    public void onClick(View v) {
        ...
    }
}

 Button對象通過setOnClickListener()方法設置點擊監聽器。例:

btn_1.setOnClickListener(new MyClickListener());

 在重寫的onClick()方法中使用getId()方法判斷響應點擊的按鈕。例:

@Override
public void onClick(View v) {
    if(v.getId()==R.id.btn_1) {...}
    else if(v.getId()==R.id.btn_2) {...}
    ...
}

View.OnLongClickListener

View.OnLongClickListener是按鈕長按監聽器。充當OnLongClickListener的對象類需要實現View.OnLongClickListener接口並重寫onLongClick()方法。例:

public class MyLongClickListener implements View.OnLongClickListener {
    ...
    @Override
    public boolean onLongClick(View v) {
        ...
        return true/false;
    }
}

 Button對象通過setOnLongClickListener()方法設置長按監聽器。例:

btn_1.setOnLongClickListener(new MyLongClickListener());

 在重寫的onLongClick()方法中使用getId()方法判斷響應長按的按鈕。例:

@Override
public boolean onLongClick(View v) {
    if(v.getId()==R.id.btn_1) {...}
    else if(v.getId()==R.id.btn_2) {...}
    return true/false;
}

onLongClick()返回false則長按之後繼續響應點擊,即onLongClick()調用後會繼續調用onClick();返回true則長按之後不響應點擊,即onLongClick()調用後不會再調用onClick()

View.OnTouchListener

View.OnTouchListener是按鈕觸摸監聽器。充當OnTouchListener的對象類需要實現View.OnTouchListener接口並重寫onTouch()方法。例:

public class MyTouchListener implements View.OnTouchListener {
    ...
    @Override
    public boolean onTouch(View v,MotionEvent event) {
        ...
        return true/false;
    }
}

 Button對象通過setOnTouchListener()方法設置觸摸監聽器。例:

btn_1.setOnTouchListener(new MyTouchListener());

 在重寫的onTouch()方法中使用getId()方法判斷響應觸摸的按鈕。使用getAction()方法判斷觸摸事件的類型,觸摸事件的類型有ACTION_DOWN(手指按下)ACTION_MOVE(手指移動)ACTION_UP(手指離開)ACTION_CANCEL(觸摸事件被攔截)。例:

@Override
public boolean onTouch(View v,MotionEvent event) {
    if(v.getId()==R.id.btn_1) {
        if(event.getAction()==MotionEvent.ACTION_DOWN) {...}
        else if(event.getAction()==MotionEvent.ACTION_MOVE) {...}
        else if(event.getAction()==MotionEvent.ACTION_UP) {...}
        else if(event.getAction()==MotionEvent.ACTION_CANCEL) {...}
    }
    else if(v.getId()==R.id.btn_2) {
        if(event.getAction()==MotionEvent.ACTION_DOWN) {...}
        else if(event.getAction()==MotionEvent.ACTION_MOVE) {...}
        else if(event.getAction()==MotionEvent.ACTION_UP) {...}
        else if(event.getAction()==MotionEvent.ACTION_CANCEL) {...}
    }
    ...
}

onTouch()返回false,系統調用完onTouch()後會繼續調用onLongClick()onClick();返回true則系統調用完onTouch()後不會調用onLongClick()onClick()
 系統調用監聽方法的先後順序:onTouch()onLongClick()onClick()

設置監聽器的方式

①使用當前Activity對象作爲按鈕監聽器:
MainActivity.java

public class MainActivity extends Activity 
                       implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button btn_1=(Button)findviewById(R.id.btn_1);
        btn_1.setOnClickListener(this);
        ...
    }
    
    @Override
    public void onCLick(View v) {
        ...
    }                                     
}                       

②使用內部類對象作爲按鈕監聽器:
MainActivity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button btn_1=(Button)findviewById(R.id.btn_1);
        btn_1.setOnClickListener(new MyClickListener());
        ...
    }
    
    private class MyClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            ...
        }
    }
}

③使用匿名內部類對象作爲按鈕監聽器:
MainActivity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button btn_1=(Button)findviewById(R.id.btn_1);
        btn_1.setOnClickListener(new View.OnClickListener(){
            ...
            @Override
            public void onClick(View v) {
                ...
            }
        }); 
        ...   
    }
}

④使用外部類對象作爲按鈕監聽器:
MainActivity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button btn_1=(Button)findviewById(R.id.btn_1);
        btn_1.setOnCLickListener(new MyClickListener());
        ...
    }
    ...
}

MyClickListener.java

public class MyClickListener implements View.OnClickListener {
    @Override 
    public void onClick(View v) {
        ...
    }
    ...
}

⑤使用xml屬性設置Click監聽方法:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout...>
    ...
    <Button
        ...
        android:id="@+id/btn_1"
        android:onClick="MyClick"
        .../>
    ...    
</LinearLayout>    

MainActivity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button btn_1=(Button)findviewById(R.id.btn_1);
        ...
    }
    
    public void MyClick(View v) {
        if(v.getId()==R.id.btn_1) {...}
        ...
    }
    ...
}

 說明:activity_main.xml中的android:onClick="MyClick"表示使用Button的android:onClick屬性爲Button設置了一個名爲MyClick的監聽方法。使用這種方式必須定義一個同名方法,在本例中即爲:public void MyClick(View v) {...}。在這個方法中可以使用getId()方法判斷響應點擊的按鈕。
 注意:只有Click可以使用Button的xml屬性設置監聽,LongClick和Touch沒有這種設置方式。
android:onClick屬性的系統採用優先級低於其它監聽方式,即一個Button同時設置android:onClick屬性與其它監聽方式時,系統會優先採用其它監聽方式。

Button的繼承

 自定義Button時會用到Button的繼承。AndroidStudio要求使用AppCompatButton代替Button用以自定義Button類的繼承。對於開發者而言,自定義Button中最有意義的方法是構造函數onTouchEvent()
 以下將以簡單實例代碼展示Button繼承的用法。代碼實現:觸摸按鈕時按鈕顏色改變,鬆開按鈕後按鈕顏色恢復。
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    ...
    android:id="@+id/linearlayout_main">
    ...  
</LinearLayout>    

button_id.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="btn_1" type="id"/>
    ...
</resources>

MyButton.java

import...
import androidx.appcompat.widget.AppCompatButton;
public class MyButton extends AppCompatButton {
    //constructors
    public MyButton(Context context) {
        super(context);
        //init button's background color
        this.setBackgroundColor(0x50ff00ff);
    }
    public MyButton(Context context,AttributeSet attrs) {
        super(context,attrs);
        //init button's background color
        this.setBackgroundColor(0x50ff00ff);
    }
    public MyButton(Context context,AttributeSet attrs,int defStyleAttr) {
        super(context,attrs,defStyleAttr);
        //init button's background color
        this.setBackgroundColor(0x50ff00ff);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction()==MotionEvent.ACTION_DOWN) {
            //color change
            this.setBackgroundColor(0x90ff00ff);
        }
        else if(event.getAction()==MotionEvent.ACTION_UP) {
            //color recover
            this.setBackgroundColor(0x50ff00ff);
        }
        return super.onTouchEvent(event);
    }
}

MainActivity.java

public class MainActivity extends Activity
                       implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LinearLayout linearlayout_main=
        (LinearLayout)findviewById(R.id.linearlayout_main);
        
        MyButton btn_1=new MyButton(this);
        LinearLayout.LayoutParams params=
                 new LinearLayout.LayoutParams(
                     ViewGroup.LayoutParams.MATCH_PARENT,
                     ViewGroup.LayoutParams.MATCH_PARENT);
        btn_1.setLayoutParams(params);
        
        linearlayout_main.addView(btn_1);   
                  
        btn_1.setText("Button1");
        btn_1.setId(R.id.btn_1);
        btn_1.setOnClickListener(this);
    }
    
    @Override 
    public void onClick(View v) {
        if(v.getId()==R.id.btn_1) {
            Toast.makText(this,"Test success!",Toast.LENGTH_SHORT).show();
        }
        ...
    }
    ...
}

歡迎指正
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章