Android Fragment onClick 按钮方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21192386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Fragment onClick button Method
提问by user3160725
I'm trying to invoke the method in my onClick (View v) XML, but does not work with Fragment. This is the error.
我正在尝试在我的 onClick (View v) XML 中调用该方法,但不适用于 Fragment。这是错误。
01-17 12:38:36.840: E/AndroidRuntime(4171): java.lang.IllegalStateException:
Could not find a method insertIntoDb(View) in the activity class main.MainActivity
for onClick handler on view class android.widget.Button with id 'btn_conferma'
Java code:
爪哇代码:
public void insertIntoDb(View v) {
...
}
XML:
XML:
<Button
android:id="@id/btn_conferma"
style="?android:attr/borderlessButtonStyle"
android:layout_width="0.0dip"
android:layout_height="45dp"
android:layout_marginLeft="2dp"
android:layout_weight="1.0"
android:background="@drawable/bottoni"
android:gravity="center_horizontal|center_vertical"
android:onClick="insertIntoDb"
android:text="SALVA"
android:textColor="#ffffff"
android:textSize="16sp" />
回答by Raghunandan
Your activity must have
你的活动必须有
public void insertIntoDb(View v) {
...
}
not Fragment .
不是片段。
If you don't want the above in activity. initialize button in fragment and set listener to the same.
如果您不想在活动中执行上述操作。在片段中初始化按钮并将侦听器设置为相同。
<Button
android:id="@+id/btn_conferma" // + missing
Then
然后
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_rssitem_detail,
container, false);
Button button = (Button) view.findViewById(R.id.btn_conferma);
button.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// do something
}
});
return view;
}
回答by cjayem13
Another option may be to have your fragment implement View.OnClickListener and override onClick(View v) within your fragment. If you need to have your fragment talk to the activity simply add an interface with desired method(s) and have the activity implement the interface and override its method(s).
另一种选择可能是让您的片段实现 View.OnClickListener 并在您的片段中覆盖 onClick(View v) 。如果您需要让您的片段与活动对话,只需添加一个具有所需方法的接口,并让活动实现该接口并覆盖其方法。
public class FragName extends Fragment implements View.OnClickListener {
public FragmentCommunicator fComm;
public ImageButton res1, res2;
int c;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_test, container, false);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
fComm = (FragmentCommunicator) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragmentCommunicator");
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
res1 = (ImageButton) getActivity().findViewById(R.id.responseButton1);
res1.setOnClickListener(this);
res2 = (ImageButton) getActivity().findViewById(R.id.responseButton2);
res2.setOnClickListener(this);
}
public void onClick(final View v) { //check for what button is pressed
switch (v.getId()) {
case R.id.responseButton1:
c *= fComm.fragmentContactActivity(2);
break;
case R.id.responseButton2:
c *= fComm.fragmentContactActivity(4);
break;
default:
c *= fComm.fragmentContactActivity(100);
break;
}
public interface FragmentCommunicator{
public int fragmentContactActivity(int b);
}
public class MainActivity extends FragmentActivity implements FragName.FragmentCommunicator{
int a = 10;
//variable a is update by fragment. ex. use to change textview or whatever else you'd like.
public int fragmentContactActivity(int b) {
//update info on activity here
a += b;
return a;
}
}
http://developer.android.com/training/basics/firstapp/starting-activity.htmlhttp://developer.android.com/training/basics/fragments/communicating.html
http://developer.android.com/training/basics/firstapp/starting-activity.html http://developer.android.com/training/basics/fragments/communicating.html
回答by CzarMatt
This is not an issue, this is a design of Android. See here:
这不是问题,这是Android的设计。见这里:
You should design each fragment as a modular and reusable activity component. That is, because each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can include one fragment in multiple activities, so you should design for reuse and avoid directly manipulating one fragment from another fragment.
您应该将每个片段设计为模块化和可重用的活动组件。也就是说,因为每个片段都定义了自己的布局和自己的行为以及自己的生命周期回调,所以您可以将一个片段包含在多个活动中,因此您应该为重用而设计,并避免直接从另一个片段操作一个片段。
A possible workaround would be to do something like this in your MainActivity:
一种可能的解决方法是在 MainActivity 中执行以下操作:
Fragment someFragment;
...onCreate etc instantiating your fragments
public void myClickMethod(View v){
someFragment.myClickMethod(v);
}
and then in your Fragment class:
然后在您的 Fragment 类中:
public void myClickMethod(View v){
switch(v.getid()){
// Your code here
}
}
回答by 18446744073709551615
The others have already said that methods in onClick are searched in activities, not fragments. Nevertheless, if you really want it, it ispossible.
其他人已经说过 onClick 中的方法是在活动中搜索的,而不是片段中。然而,如果你真的想要它,这是可能的。
Basically, each view has a tag (probably null). We set the root view's tag to the fragment that inflated that view. Then, it is easy to search the view parents and retrieve the fragment containing the clicked button. Now, we find out the method name and use reflection to call the same method from the retrieved fragment. Easy!
基本上,每个视图都有一个标签(可能为空)。我们将根视图的标签设置为膨胀该视图的片段。然后,很容易搜索父视图并检索包含单击按钮的片段。现在,我们找出方法名称并使用反射从检索到的片段中调用相同的方法。简单!
in a class that extends Fragment
:
在一个扩展的类中Fragment
:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_id, container, false);
OnClickFragments.registerTagFragment(rootView, this); // <========== !!!!!
return rootView;
}
public void onButtonSomething(View v) {
Log.d("~~~","~~~ MyFragment.onButtonSomething");
// whatever
}
all activities are derived from the same ButtonHandlingActivity:
所有活动都源自同一个 ButtonHandlingActivity:
public class PageListActivity extends ButtonHandlingActivity
ButtonHandlingActivity.java:
ButtonHandlingActivity.java:
public class ButtonHandlingActivity extends Activity {
public void onButtonSomething(View v) {
OnClickFragments.invokeFragmentButtonHandlerNoExc(v);
//or, if you want to handle exceptions:
// try {
// OnClickFragments.invokeFragmentButtonHandler(v);
// } catch ...
}
}
It has to define methods for all xml onClick handlers.
它必须为所有 xml onClick 处理程序定义方法。
com/example/customandroid/OnClickFragments.java:
com/example/customandroid/OnClickFragments.java:
package com.example.customandroid;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Fragment;
import android.view.View;
public abstract class OnClickFragments {
public static class FragmentHolder {
Fragment fragment;
public FragmentHolder(Fragment fragment) {
this.fragment = fragment;
}
}
public static Fragment getTagFragment(View view) {
for (View v = view; v != null; v = (v.getParent() instanceof View) ? (View)v.getParent() : null) {
Object tag = v.getTag();
if (tag != null && tag instanceof FragmentHolder) {
return ((FragmentHolder)tag).fragment;
}
}
return null;
}
public static String getCallingMethodName(int callsAbove) {
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[callsAbove+1].getMethodName();
return methodName;
}
public static void invokeFragmentButtonHandler(View v, int callsAbove) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
String methodName = getCallingMethodName(callsAbove+1);
Fragment f = OnClickFragments.getTagFragment(v);
Method m = f.getClass().getMethod(methodName, new Class[] { View.class });
m.invoke(f, v);
}
public static void invokeFragmentButtonHandler(View v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
invokeFragmentButtonHandler(v,1);
}
public static void invokeFragmentButtonHandlerNoExc(View v) {
try {
invokeFragmentButtonHandler(v,1);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public static void registerTagFragment(View rootView, Fragment fragment) {
rootView.setTag(new FragmentHolder(fragment));
}
}
And the next adventure will be proguard obfuscation...
而下一次冒险将是混淆混淆......
PS
聚苯乙烯
It is of course up to you to design your application so that the data live in the Modelrather than in Activities or Fragments (which are Controllersfrom the MVC, Model-View-Controllerpoint of view). The Viewis what you define via xml, plus the custom view classes (if you define them, most people just reuse what already is). A rule of thumb: if some data definitely must survive the screen turn, they belong to Model.
当然,由您来设计您的应用程序,以便数据存在于模型中,而不是存在于活动或片段中(从MVC 的角度来看,它们是控制器,模型-视图-控制器)。该视图是您通过XML定义是什么,以及自定义视图类(如果你定义它们,大多数人只是重用已经是什么)。一条经验法则:如果某些数据肯定必须在屏幕转动后幸存下来,那么它们属于Model。
回答by Pong Petrung
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.writeqrcode_main, container, false);
// Inflate the layout for this fragment
txt_name = (TextView) view.findViewById(R.id.name);
txt_usranme = (TextView) view.findViewById(R.id.surname);
txt_number = (TextView) view.findViewById(R.id.number);
txt_province = (TextView) view.findViewById(R.id.province);
txt_write = (EditText) view.findViewById(R.id.editText_write);
txt_show1 = (Button) view.findViewById(R.id.buttonShow1);
txt_show1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("Onclick","Onclick");
txt_show1.setVisibility(View.INVISIBLE);
txt_name.setVisibility(View.VISIBLE);
txt_usranme.setVisibility(View.VISIBLE);
txt_number.setVisibility(View.VISIBLE);
txt_province.setVisibility(View.VISIBLE);
}
});
return view;
}
You OK !!!!
你还好吗 !!!!
回答by Jayant Dhingra
For Kotlin users:
对于 Kotlin 用户:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?) : View?
{
// Inflate the layout for this fragment
var myView = inflater.inflate(R.layout.fragment_home, container, false)
var btn_test = myView.btn_test as Button
btn_test.setOnClickListener {
textView.text = "hunny home fragment"
}
return myView
}