蜂窩前(Android 3),每一個活動均已註冊,以經過佈局XML中的onClick
標記處理按鈕單擊: java
android:onClick="myClickMethod"
在該方法中,您可使用view.getId()
和switch語句來執行按鈕邏輯。 android
隨着Honeycomb的引入,我將這些活動分解爲片斷,能夠在許多不一樣的活動中重用這些片斷。 按鈕的大多數行爲都是獨立於活動的,我但願代碼駐留在Fragments文件中, 而無需使用爲每一個按鈕註冊OnClickListener
的舊方法(1.6版以前)。 app
final Button button = (Button) findViewById(R.id.button_id); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Perform action on click } });
問題是當個人佈局膨脹時,仍然是託管活動正在接收按鈕點擊,而不是單個片斷。 是否有一個好的方法 ide
在處理片斷時,我寧願使用代碼中的單擊處理,也不肯使用XML中的onClick
屬性。 佈局
將您的活動遷移到片斷時,這變得更加容易。 您能夠直接從每一個case
塊調用click處理程序(之前在XML中設置爲android:onClick
)。 this
findViewById(R.id.button_login).setOnClickListener(clickListener); ... OnClickListener clickListener = new OnClickListener() { @Override public void onClick(final View v) { switch(v.getId()) { case R.id.button_login: // Which is supposed to be called automatically in your // activity, which has now changed to a fragment. onLoginClick(v); break; case R.id.button_logout: ... } } }
在處理片斷中的點擊時,對我來講,這比android:onClick
更簡單。 spa
我更喜歡使用如下解決方案來處理onClick事件。 這也適用於活動和片斷。 code
public class StartFragment extends Fragment implements OnClickListener{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_start, container, false); Button b = (Button) v.findViewById(R.id.StartButton); b.setOnClickListener(this); return v; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.StartButton: ... break; } } }
這是另外一種方式: orm
1,建立一個BaseFragment像這樣: 事件
public abstract class BaseFragment extends Fragment implements OnClickListener
2.使用
public class FragmentA extends BaseFragment
代替
public class FragmentA extends Fragment
3,活動中
public class MainActivity extends ActionBarActivity implements OnClickListener
和
BaseFragment fragment = new FragmentA; public void onClick(View v){ fragment.onClick(v); }
但願能幫助到你。
除了Blundell的答案,
若是您有更多片斷,而且擁有大量的onClicks:
活動:
Fragment someFragment1 = (Fragment)getFragmentManager().findFragmentByTag("someFragment1 "); Fragment someFragment2 = (Fragment)getFragmentManager().findFragmentByTag("someFragment2 "); Fragment someFragment3 = (Fragment)getFragmentManager().findFragmentByTag("someFragment3 "); ...onCreate etc instantiating your fragments public void myClickMethod(View v){ if (someFragment1.isVisible()) { someFragment1.myClickMethod(v); }else if(someFragment2.isVisible()){ someFragment2.myClickMethod(v); }else if(someFragment3.isVisible()){ someFragment3.myClickMethod(v); } }
在您的片斷中:
public void myClickMethod(View v){ switch(v.getid()){ // Just like you were doing } }
Butterknife多是解決混亂問題的最佳解決方案。 它使用註釋處理器生成所謂的「舊方法」樣板代碼。
可是onClick方法仍然能夠與自定義充氣機一塊兒使用。
@Override public View onCreateView(LayoutInflater inflater, ViewGroup cnt, Bundle state) { inflater = FragmentInflatorFactory.inflatorFor(inflater, this); return inflater.inflate(R.layout.fragment_main, cnt, false); }
public class FragmentInflatorFactory implements LayoutInflater.Factory { private static final int[] sWantedAttrs = { android.R.attr.onClick }; private static final Method sOnCreateViewMethod; static { // We could duplicate its functionallity.. or just ignore its a protected method. try { Method method = LayoutInflater.class.getDeclaredMethod( "onCreateView", String.class, AttributeSet.class); method.setAccessible(true); sOnCreateViewMethod = method; } catch (NoSuchMethodException e) { // Public API: Should not happen. throw new RuntimeException(e); } } private final LayoutInflater mInflator; private final Object mFragment; public FragmentInflatorFactory(LayoutInflater delegate, Object fragment) { if (delegate == null || fragment == null) { throw new NullPointerException(); } mInflator = delegate; mFragment = fragment; } public static LayoutInflater inflatorFor(LayoutInflater original, Object fragment) { LayoutInflater inflator = original.cloneInContext(original.getContext()); FragmentInflatorFactory factory = new FragmentInflatorFactory(inflator, fragment); inflator.setFactory(factory); return inflator; } @Override public View onCreateView(String name, Context context, AttributeSet attrs) { if ("fragment".equals(name)) { // Let the Activity ("private factory") handle it return null; } View view = null; if (name.indexOf('.') == -1) { try { view = (View) sOnCreateViewMethod.invoke(mInflator, name, attrs); } catch (IllegalAccessException e) { throw new AssertionError(e); } catch (InvocationTargetException e) { if (e.getCause() instanceof ClassNotFoundException) { return null; } throw new RuntimeException(e); } } else { try { view = mInflator.createView(name, null, attrs); } catch (ClassNotFoundException e) { return null; } } TypedArray a = context.obtainStyledAttributes(attrs, sWantedAttrs); String methodName = a.getString(0); a.recycle(); if (methodName != null) { view.setOnClickListener(new FragmentClickListener(mFragment, methodName)); } return view; } private static class FragmentClickListener implements OnClickListener { private final Object mFragment; private final String mMethodName; private Method mMethod; public FragmentClickListener(Object fragment, String methodName) { mFragment = fragment; mMethodName = methodName; } @Override public void onClick(View v) { if (mMethod == null) { Class<?> clazz = mFragment.getClass(); try { mMethod = clazz.getMethod(mMethodName, View.class); } catch (NoSuchMethodException e) { throw new IllegalStateException( "Cannot find public method " + mMethodName + "(View) on " + clazz + " for onClick"); } } try { mMethod.invoke(mFragment, v); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } } } }