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();
        }
        ...
    }
    ...
}

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