Android OnClickListener - ระบุปุ่ม


134

ฉันมีกิจกรรม:

public class Mtest extends Activity {
  Button b1;
  Button b2;
  public void onCreate(Bundle savedInstanceState) {
    ...
    b1 = (Button) findViewById(R.id.b1);
    b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(myhandler);
    b2.setOnClickListener(myhandler);
    ...
  }
  View.OnClickListener myhandler = new View.OnClickListener() {
    public void onClick(View v) {
      // MY QUESTION STARTS HERE!!!
      // IF b1 do this
      // IF b2 do this
      // MY QUESTION ENDS HERE!!!
    }
  }
}

ฉันจะตรวจสอบได้อย่างไรว่าปุ่มใดถูกคลิก?


1
การเปรียบเทียบห้าวิธีที่แตกต่างกันในการเพิ่ม OnClickListeners สำหรับปุ่มหลายปุ่ม
Suragch

คำตอบ:


199

คุณจะได้เรียนรู้วิธีการทำในวิธีง่ายๆคือ:

public class Mtest extends Activity {
  Button b1;
  Button b2;
  public void onCreate(Bundle savedInstanceState) {
    ...
    b1 = (Button) findViewById(R.id.b1);
    b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(myhandler1);
    b2.setOnClickListener(myhandler2);
    ...
  }
  View.OnClickListener myhandler1 = new View.OnClickListener() {
    public void onClick(View v) {
      // it was the 1st button
    }
  };
  View.OnClickListener myhandler2 = new View.OnClickListener() {
    public void onClick(View v) {
      // it was the 2nd button
    }
  };
}

หรือหากคุณกำลังทำงานกับเครื่องมือคลิกรายการเดียวคุณสามารถทำได้:

View.OnClickListener myOnlyhandler = new View.OnClickListener() {
  public void onClick(View v) {
      switch(v.getId()) {
        case R.id.b1:
          // it was the first button
          break;
        case R.id.b2:
          // it was the second button
          break;
      }
  }
}

แม้ว่าฉันไม่แนะนำให้ทำเช่นนั้นเนื่องจากคุณจะต้องเพิ่มifปุ่มสำหรับแต่ละปุ่มที่คุณใช้ มันยากที่จะรักษา


1
ที่จริงไม่ถูกต้อง Viewไม่ใช่ a Buttonแต่Buttonเป็นไฟล์View. แม้ว่าคุณสามารถส่งViewไฟล์Button. โปรดทราบว่าวิธีที่สองไม่แนะนำให้ทำ ... บางที v นั้นอาจไม่ใช่ปุ่มซึ่งจะทำให้เกิดข้อยกเว้นในการร่าย
Cristian

2
จริงๆแล้วไม่แนะนำทั้งสองวิธีดูคำตอบของฉัน
ognian

จริงๆแล้วมันค่อนข้างง่ายที่จะแทนที่ if, elses ด้วยคำสั่งกรณีสวิตช์เดียวที่คุณเปิด id ของมุมมองและเคสเป็น id จาก R.java
slayton

แค่สงสัยว่าทำไมคุณถึงส่ง v ไปที่ปุ่ม getId () ถูกกำหนดให้กับ Views เช่นกัน ดังนั้นฉันจะไม่แนะนำวิธีที่ 2 จริงๆ แต่ชอบวิธีแก้ปัญหาของคริสเตียนมากกว่า!
Nuala

77

หรือจะลองแบบเดียวกัน แต่ไม่มีผู้ฟัง คำจำกัดความ XML ของปุ่มของคุณ:

android:onClick="ButtonOnClick"

และในรหัสของคุณกำหนดวิธีการButtonOnClick:

public void ButtonOnClick(View v) {
    switch (v.getId()) {
      case R.id.button1:
        doSomething1();
        break;
      case R.id.button2:
        doSomething2();
        break;
      }
}

3
สะอาดกว่าคำตอบอื่น ๆ ที่ใช้ตัวจัดการเหตุการณ์ifแถลงการณ์และผู้ฟังมากมาย Listener เป็นสิ่งที่ดีหากสร้างปุ่มในรันไทม์ แต่มักไม่เป็นเช่นนั้น
Dennis

6
ในขณะที่วิธีการที่แตกต่างกันที่น่าสนใจ XML hooks สำหรับผู้ฟังนั้นหยาบรอบ ๆ มุมด้วยFragments เนื่องจากการเรียกกลับต้องอยู่ในกิจกรรม (ไม่ใช่ส่วนย่อย)
donfede

ความน่าจะเป็นของฉันคือ doSomething2 () ไม่สามารถเข้าถึงได้โดยไม่ต้องโยน InvocationTargetException หรือ NullPointerException (หรือทั้งสองอย่าง)
Quasaur

1
เพียงแค่ข้อคิดเห็น: คำสั่ง "โดยไม่มีผู้ฟัง" ที่นี่ไม่ถูกต้อง คุณกำลังประกาศ Listener ใน XML เท่านั้นนั่นคือทั้งหมดที่
Hubert Grzeskowiak

42

ฉันชอบ:

class MTest extends Activity implements OnClickListener {
    public void onCreate(Bundle savedInstanceState) {
    ...
    Button b1 = (Button) findViewById(R.id.b1);
    Button b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(this);
    b2.setOnClickListener(this);
    ...
}

แล้ว:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.b1:
            ....
            break;
        case R.id.b2:
            ....
            break;
    }   
}

Switch- caseดูแลรักษาง่ายกว่าif- elseและการใช้งานนี้ไม่จำเป็นต้องสร้างตัวแปรคลาสจำนวนมาก


สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบ คุณต้องใช้OnClickListener-android.view.Viewไม่ใช่OnClickListener-android.content.DialogInterface
gkiko

16

ห้าวิธีในการเชื่อมต่อผู้ฟังเหตุการณ์เป็นบทความที่ยอดเยี่ยมที่อธิบายถึงวิธีต่างๆในการตั้งค่าตัวฟังเหตุการณ์เดียว ขอขยายความตรงนี้สำหรับผู้ฟังหลายคน

1. คลาสสมาชิก

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //attach an instance of HandleClick to the Button
        HandleClick handleClick = new HandleClick();
        findViewById(R.id.button1).setOnClickListener(handleClick);
        findViewById(R.id.button2).setOnClickListener(handleClick);
    }    
    private class HandleClick implements OnClickListener{
        public void onClick(View view) {
            switch(view.getId()) {
            case R.id.button1:
                // do stuff
                break;
            case R.id.button2:
                // do stuff
                break;
            }
        }
    }
}

2. ประเภทอินเทอร์เฟซ

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(handleClick);
        findViewById(R.id.button2).setOnClickListener(handleClick);
    }
    private OnClickListener handleClick = new OnClickListener() {
        public void onClick(View view) {
            switch (view.getId()) {
            case R.id.button1:
                // do stuff
                break;
            case R.id.button2:
                // do stuff
                break;
            }
        }
    };
}

3. ชั้นในนิรนาม

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                // do stuff
            }
        });
        findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                // do stuff
            }
        });
    }
}

4. การนำไปใช้ในกิจกรรม

public class main extends Activity implements OnClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            // do stuff
            break;
        case R.id.button2:
            // do stuff
            break;
        }
    }
}

5. แอตทริบิวต์ในมุมมองเค้าโครงสำหรับเหตุการณ์ OnClick

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void HandleClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            // do stuff
            break;
        case R.id.button2:
            // do stuff
            break;
        }
    }
}

และใน xml:

<Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="HandleClick" />
<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="HandleClick" />

12

หากคุณไม่ต้องการบันทึกอินสแตนซ์ของปุ่ม 2 ในรหัสคลาสให้ทำตามวิธีนี้ที่ดีกว่า (ชัดเจนและรวดเร็วกว่า !!):

public void buttonPress(View v) {
  switch (v.getId()) {
    case R.id.button_one:
        // do something
        break;
    case R.id.button_two:
        // do something else
        break;
    case R.id.button_three:
        // i'm lazy, do nothing
        break;
  }
}

12

อีกวิธีในการทำคือฟังคนเดียวจากกิจกรรมเช่นนี้:

public class MyActivity extends Activity implements OnClickListener {
    .......  code

    //my listener
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.mybutton) { 
            DoSomething();
            return;
        }

        if (v.getId() == R.id.mybutton2) { 
            DoSomething2();
            return;
        }
    }
}

ฉันชอบทำด้วย IF เดียวแทนที่จะเป็นสวิตช์อื่น แต่ถ้าคุณต้องการสิ่งนั้นคุณควรทำ:

//my listener
@Override
public void onClick(View v) {
    switch(v.getId()) {
        case R.id.mybutton:
        { 
             DoSomething();
             break;
        }

        case R.id.mybutton2:
        {
            DoSomething();
            break;
        }
    }
}

9

วิธีที่ดีที่สุดคือการswitchเชื่อมต่อระหว่าง v.getId () การมี OnClickListener ที่ไม่ระบุชื่อแยกต่างหากสำหรับแต่ละปุ่มจะใช้หน่วยความจำมากขึ้น ไม่จำเป็นต้องแคสต์ View to Button การใช้ if-else เมื่อสวิตช์ทำได้ช้าและอ่านยากกว่า ในแหล่งที่มาของ Android คุณมักจะสังเกตเห็นการเปรียบเทียบการอ้างอิงโดย if-else:

if (b1 == v) {
 // ...
} else if (b2 == v) {

ฉันไม่รู้ว่าทำไมพวกเขาถึงเลือกวิธีนี้ แต่มันก็ได้ผลเช่นกัน


เนื่องจากเป็นไปไม่ได้อีกต่อไปตั้งแต่ v14 โดยที่รหัสไม่ได้รับการปฏิบัติไม่คงที่
user1324936

@ognian ฉันติดตามที่นี่เพราะคุณบอกว่าคำตอบหลักใช้วิธีการที่เลิกใช้แล้ว ปัจจุบันมีการเปิดตัว Android 5.0 Lollipop คำตอบของคุณยังคงเป็นจริงหรือเวลาทำให้มันกลายเป็นเท็จอย่างที่ความคิดเห็นข้างบนแนะนำ? ฉันไม่รู้ว่าจะคิดอย่างไรหรือจะไปทางไหนจากที่นี่
SebasSBM

7

ใช้ setTag ();

แบบนี้:

@Override    
public void onClick(View v) {     
    int tag = (Integer) v.getTag();     
    switch (tag) {     
    case 1:     
        System.out.println("button1 click");     
        break;     
    case 2:     
        System.out.println("button2 click");     
       break;   
    }     
}     

ฉันมาที่นี่เพื่อค้นหาวิธีส่งผ่านพารามิเตอร์เพิ่มเติมไปยังตัวจัดการนี่คือสิ่งที่ฉันต้องการ สามารถประกาศแท็กในมาร์กอัป
cessor

4

นอกเหนือจากคำตอบของ Cristian C (ขออภัยฉันไม่มีความสามารถในการแสดงความคิดเห็น) หากคุณสร้างตัวจัดการเพียงปุ่มเดียวสำหรับทั้งสองปุ่มคุณสามารถเปรียบเทียบ v กับ b1 และ b2 ได้โดยตรงหรือหากคุณต้องการเปรียบเทียบด้วย ID คุณ ไม่จำเป็นต้องร่าย v ไปที่ Button (View มี getId () method ด้วย) และวิธีนี้ก็ไม่ต้องกังวลกับข้อยกเว้นในการร่าย


อีกทางเลือกหนึ่งคือทำ "if (v instanceof Button) {// Cast to Button and do stuff here}"
Andy Zhang


1
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(this);

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    if(v.getId() == R.id.button1){
        Toast.makeText(context, "Button 1 Click", Toast.LENGTH_LONG).show();
    }
}

ตรวจสอบบทความนี้เพื่อดูรายละเอียดเพิ่มเติม


นี่เป็นเพียงการทำซ้ำบางคำตอบที่มีอยู่
ปัง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.