目錄
簡介
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對象。由於Width
和Height
等是View的必須屬性,需要先使用ViewGroup.LayoutParams創建佈局參數對象,再使用setLayoutParams()
方法爲Button設置Width
和Height
等必須屬性。例如:
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 resource
xml資源文件,並創建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();
}
...
}
...
}
歡迎指正