smi*_*324 425 xml android button android-fragments
Pre-Honeycomb(Android 3),每个Activity都已注册,可通过onClickLayout的XML中的标签处理按钮点击:
android:onClick="myClickMethod"
Run Code Online (Sandbox Code Playgroud)
在该方法中,您可以使用view.getId()和switch语句来执行按钮逻辑.
随着Honeycomb的推出,我将这些活动分解为碎片,可以在许多不同的活动中重复使用.按钮的大部分行为都是与Activity无关的,我希望代码驻留在Fragments文件中,而不使用OnClickListener为每个按钮注册的旧(pre 1.6)方法.
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
Run Code Online (Sandbox Code Playgroud)
问题是,当我的布局被夸大时,它仍然是接收按钮点击的托管活动,而不是单个碎片.对两者都有好的方法
Ado*_*ncz 593
我更喜欢使用以下解决方案来处理onClick事件.这适用于Activity和Fragments.
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Blu*_*ell 170
你可以这样做:
活动:
Fragment someFragment;
//...onCreate etc instantiating your fragments
public void myClickMethod(View v) {
someFragment.myClickMethod(v);
}
Run Code Online (Sandbox Code Playgroud)
分段:
public void myClickMethod(View v) {
switch(v.getId()) {
// Just like you were doing
}
}
Run Code Online (Sandbox Code Playgroud)
回应@Ameen谁想要更少的耦合,所以片段是可重复使用的
接口:
public interface XmlClickable {
void myClickMethod(View v);
}
Run Code Online (Sandbox Code Playgroud)
活动:
XmlClickable someFragment;
//...onCreate, etc. instantiating your fragments casting to your interface.
Run Code Online (Sandbox Code Playgroud)
public void myClickMethod(View v) {
someFragment.myClickMethod(v);
}
Run Code Online (Sandbox Code Playgroud)
分段:
public class SomeFragment implements XmlClickable {
//...onCreateView, etc.
@Override
public void myClickMethod(View v) {
switch(v.getId()){
// Just like you were doing
}
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*pin 28
我认为问题是视图仍然是活动,而不是片段.片段没有自己的任何独立视图,并附加到父活动视图.这就是为什么事件最终在Activity中,而不是片段.不幸的是,但我认为你需要一些代码来完成这项工作.
我在转换过程中一直在做的只是添加一个调用旧事件处理程序的单击侦听器.
例如:
final Button loginButton = (Button) view.findViewById(R.id.loginButton);
loginButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
onLoginClicked(v);
}
});
Run Code Online (Sandbox Code Playgroud)
Ald*_*epa 23
我最近解决了这个问题,无需向上下文Activity添加方法或必须实现OnClickListener.我不确定它是否是一个"有效"的解决方案,但它确实有效.
基于:https://developer.android.com/tools/data-binding/guide.html#binding_events
它可以通过数据绑定来完成:只需将您的片段实例添加为变量,然后您可以使用onClick链接任何方法.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.testapp.fragments.CustomFragment">
<data>
<variable android:name="fragment" android:type="com.example.testapp.fragments.CustomFragment"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_place_black_24dp"
android:onClick="@{() -> fragment.buttonClicked()}"/>
</LinearLayout>
</layout>
Run Code Online (Sandbox Code Playgroud)
片段链接代码将是......
public class CustomFragment extends Fragment {
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_person_profile, container, false);
FragmentCustomBinding binding = DataBindingUtil.bind(view);
binding.setFragment(this);
return view;
}
...
}
Run Code Online (Sandbox Code Playgroud)
在使用onClick片段时,我宁愿在代码中使用单击处理而不是使用XML中的属性.
将活动迁移到片段时,这变得更加容易.您可以android:onClick直接从每个case块调用单击处理程序(以前设置为XML).
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:
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
在处理碎片中的点击时,这看起来比我简单android:onClick.
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);
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是另一种方式:
1.像这样创建一个BaseFragment:
public abstract class BaseFragment extends Fragment implements OnClickListener
Run Code Online (Sandbox Code Playgroud)
2.使用
public class FragmentA extends BaseFragment
Run Code Online (Sandbox Code Playgroud)
代替
public class FragmentA extends Fragment
Run Code Online (Sandbox Code Playgroud)
3.在你的活动中:
public class MainActivity extends ActionBarActivity implements OnClickListener
Run Code Online (Sandbox Code Playgroud)
和
BaseFragment fragment = new FragmentA;
public void onClick(View v){
fragment.onClick(v);
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你.
在我的用例中,我需要将 50 个奇数的 ImageView 挂接到单个 onClick 方法中。我的解决方案是遍历片段内的视图并在每个视图上设置相同的 onclick 侦听器:
final View.OnClickListener imageOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
chosenImage = ((ImageButton)v).getDrawable();
}
};
ViewGroup root = (ViewGroup) getView().findViewById(R.id.imagesParentView);
int childViewCount = root.getChildCount();
for (int i=0; i < childViewCount; i++){
View image = root.getChildAt(i);
if (image instanceof ImageButton) {
((ImageButton)image).setOnClickListener(imageOnClickListener);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
241967 次 |
| 最近记录: |