简体   繁体   English

是否有比调用onClickListener更好的方法来启动按钮单击上的新活动?

[英]Is there a better way of starting a new activity on button click that calling an onClickListener?

Is there a better way of starting a new activity on a button click than using the onClick attribute to specify a callback method as in the example below? 是否有比使用onClick属性指定回调方法更好的方法来启动按钮单击上的新活动,如下面的示例所示?

--- xml --- -xml-

<Button
    android:id="@+id/button1"
    android:onClick="someMethod"
    android:text="@string/someString" />

--- java --- -Java-

public void someMethod(View view) {
    startActivity(new Intent(this, SomeActivity.class));
}

I would rather like to specify the name of the activity to be started than the name of a callback method. 我想指定要启动的活动的名称,而不是回调方法的名称。 Like this: 像这样:

<Button
    android:id="@+id/button1"
    android:onClick="SomeActivity"
    android:text="@string/someString" />
  • I don't want to subclass the Button class. 我不想继承Button类。
  • I don't want to specify the same callback method for all buttons and have a switch case in the callback method that starts the correct activity. 我不想为所有按钮指定相同的回调方法,并且不想在启动正确活动的回调方法中使用开关盒。
  • Adding a custom xml attribute to the button that is specifying the activity to start (if it is possible?) 将自定义xml属性添加到指定要开始的活动的按钮(如果可能)?

As a solution I would recommend the following. 作为解决方案,我建议以下内容。 Please excuse the pseudo-like non-compiling (probably) code: 请原谅伪类非编译(可能)代码:

Button a = findViewById(R.id.button1);
Button b = findViewById(R.id.button2);

// Strings to be fed to the intent. You can use YourActivity.getClass() as well here
String mFirstTag  = "your.first.activity.class"
String mSecondTag = "your.second.activity.class"

// This is critical as it will be used by the listener
a.setTag(mFirstTag);
b.setTag(mSecondTag);

// Self explanatory
a.setOnClickListener(mClickListener);
b.setOnClickListener(mClickListener);


// This listener will grab the "tag" object from the clicked view.
// It will be the same tag which we previously set on those buttons.
private OnClickListener mClickListener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent i = new Intent(v.getTag()); // Maybe you'll need toString(), or a cast here
        startActivity(i);
    }
}

I hope you get the general idea. 希望您能大致了解。

This is what I came up with thanks to Jitsu and Mike M. 这就是我对Jitsu和Mike M的感谢。

The Activity to be started when a button is pressed is specified using the android:tag xml attribute and the constructor will set the onClickListeners to all buttons in the View. 使用android:tag xml属性指定按下按钮时要启动的Activity,构造函数会将onClickListeners设置为View中的所有按钮。

This way I don't have to: 这样,我不必:

  1. Implement a onClick method for every button. 为每个按钮实现一个onClick方法。
  2. Implement one common onClick method with a switch statement that handles all buttons. 使用处理所有按钮的switch语句实现一个常见的onClick方法。
  3. Subclass Button. 子类按钮。
  4. Create my own xml attribute. 创建我自己的xml属性。

--- xml --- -xml-

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/MainActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.playground.MainActivity" >

        <Button
            android:id="@+id/button1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:tag="showActivity"
            android:text="@string/somestring" />
</RelativeLayout>

--- java --- -Java-

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        connectButtonClickListeners(findViewById(R.id.MainActivity));
    }

    // Walk down the View tree starting with parent and connect an onClickListener to each Button.
    private void connectButtonClickListeners(View parent) {
        if (parent == null)
            return;

        LinkedList<View> list = new LinkedList<View>();
        list.add(parent);

        while (list.isEmpty() == false) {
            View v = list.pollFirst();
            if (v instanceof ViewGroup) {
                ViewGroup vg = (ViewGroup) v;
                for (int i = 0; i < vg.getChildCount(); i++)
                    list.add(vg.getChildAt(i));
            } else if (v instanceof Button) {
                Button b = (Button) v;
                b.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        // TODO: Start the new Activity.
                        System.out.println("Clicked!" + v.getTag());
                    }
                });
            }
        }

It's simple. 这很简单。 Subclass Button in a separate class file, MySpecialButton.java : 一个单独的类文件MySpecialButton.java中的Subclass Button

public class MySpecialButton extends Button {
  public MySpecialButton(Context context) {
     super(context);
     setupOnClickListener();
  }
  public MySpecialButton(Context context, AttributeSet attrs) {
     super(context);
     setupOnClickListener();
  }
  public MySpecialButton(Context context, AttributeSet attrs, int defStyle) {
     super(context);
     setupOnClickListener();
  }

  protected void setupOnClickListener() {
     setOnClickListener(new OnClickListener() {
          @Override
          public void onClick(View v) {
             startActivity(...);
          }
     });
  }
}

I haven't compiled this code, I wrote it in a hurry, but should work. 我尚未编译此代码,我急忙编写了它,但应该可以工作。

Then in your XML, instead of Button declare your view as com.yourpacket.yourappname.yourpackage.MySpecialButton . 然后在您的XML中,而不是Button将您的视图声明为com.yourpacket.yourappname.yourpackage.MySpecialButton

EDIT: You do need to add some things in the code, but you should manage (context reference, import statements etc.). 编辑:您确实需要在代码中添加一些内容,但是您应该进行管理(上下文引用,导入语句等)。

I like this method. 我喜欢这种方法。 No switch statement required. 无需switch语句。

Each button gets the same onClickListener and a tag with a class name for the new activity: 每个按钮都具有相同的onClickListener和带有新活动的类名称的标签:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="startActivityForTag"
    android:tag=".HelloActivity"
    android:text="Say hello" >
</Button>

The click listener contructs a class from the view tag: 点击侦听器通过view标记构造一个类:

public void startActivityForTag(View v) {
    String name = v.getTag().toString();
    // if name is not fully-qualified, add the package name
    if (name.startsWith(".")) {
        name = getPackageName() + name;
    }
    try {
        startActivity(new Intent(this, Class.forName(name)));
    } catch (ClassNotFoundException e) { ; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM