Android 即使显示其他片段,ViewPager onClickListener 也会做出反应
Android ViewPager onClickListener reacts even if other fragment is show
我有一个包含两个片段的 ViewPager。一个 fragment
什么都不包含,另一个 fragment
包含 gridview
和 ImageViews
。
ImageViews
有一组 onClickListener
。
到目前为止一切正常......但是当我在什么都不包含的片段上并点击其他片段的 onClickListener 某处时,即使它的元素不可见,imagview 也会对我的点击做出反应。
我可以更改我的 onClickListener
以便它检查显示的是哪个片段,但这真的是我应该做的吗???感觉有点脏
这是我的 FragmentStatePageAdapter
public class OwnPagerAdapter extends FragmentStatePagerAdapter{
private BackgroundImage backgroundImage = new BackgroundImage();
private Apps apps = new Apps();
private Home_Screen ac;
public OwnPagerAdapter(FragmentManager fm, Home_Screen activity) {
super(fm);
this.ac = activity;
}
@Override
public Fragment getItem(int position) {
if(position == 0) {
return backgroundImage;
}else if(position == 1) {
return this.apps;
}
return null;
}
@Override
public int getCount() {
return 2;
}
}
这是我的 BaseAdapter
public class AppAdapter extends BaseAdapter {
private AppLauncher launcherListener = new AppLauncher();
private ArrayList<ApplicationInfo> appList;
private Context ctx;
public AppAdapter(ArrayList<ApplicationInfo> listOfApps, Context ctx){
this.appList = listOfApps;
this.ctx = ctx;
}
@Override
public int getCount() {
return this.appList.size();
}
@Override
public Object getItem(int i) {
ImageView v = new ImageView(this.ctx);
v.setImageDrawable(this.appList.get(i).loadIcon(this.ctx.getPackageManager()));
return v;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
if(view != null){
((ImageView) view).setImageDrawable(this.appList.get(i).loadIcon(this.ctx.getPackageManager()));
view.setTag(i);
return view;
}
ImageView v = new ImageView(this.ctx);
v.setImageDrawable(this.appList.get(i).loadIcon(this.ctx.getPackageManager()));
v.setScaleType(ImageView.ScaleType.CENTER);
v.setOnClickListener(launcherListener);
v.setTag(i);
return v;
}
private class AppLauncher implements View.OnClickListener {
@Override
public void onClick(View view) {
ctx.startActivity(ctx.getPackageManager().getLaunchIntentForPackage(appList.get((int) view.getTag()).packageName));
}
}
}
那是我的片段class
public class Apps extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<ApplicationInfo>>{
private GridView gridview;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getLoaderManager().initLoader(1, null, this).forceLoad();
View rootView = inflater.inflate(R.layout.fragment_apps, container, false);
this.gridview = (GridView)rootView.findViewById(R.id.apptable);
return rootView;
}
@Override
public Loader<ArrayList<ApplicationInfo>> onCreateLoader(int id, Bundle args) {
return new AppLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<ArrayList<ApplicationInfo>> loader, ArrayList<ApplicationInfo> data) {
Toast.makeText(getActivity(), "Done with loading Apps", Toast.LENGTH_LONG).show();
this.gridview.setAdapter(new AppAdapter(data,getActivity()));
}
@Override
public void onLoaderReset(Loader<ArrayList<ApplicationInfo>> loader) {
}
}
虽然我找不到您问题的任何具体原因,但我必须建议一种更简洁的方法来实现您正在寻找的相同结果,使用内部 class 只是为了捕获点击事件是肮脏的,而且是不必要的.使用此方法很有可能也能解决您的问题。
为什么不在整个 gridview 上使用 OnItemClickListener,而不是使用实现 OnClickListener 然后手动为每个项目设置它的 AppLauncher class?它将处理每个项目的点击事件,并且仅特定于您的 gridview 中的项目,因此您不必像使用内部 classes 那样担心任何泄漏。
在您的片段中实现 OnItemClickListener :
public class Apps extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<ApplicationInfo>>, OnItemClickListener
然后在片段的 onCreate 中简单地将适配器设置为 gridview:
gridview.setOnItemClickListener(this);
并实施必要的方法:
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
getActivity().startActivity(getActivity().getPackageManager().getLaunchIntentForPackage(appList.get(position).packageName));
}
现在您可以从 gridview 的适配器中删除 OnClickListener 逻辑,它应该可以正常工作,我猜它也可以解决您的问题,即使不能,嘿,至少您最终会得到一个更清晰的代码。
关于您的代码,我觉得奇怪的另一件事是您覆盖了 getItemId() 但始终 return 0,请确保这是您正在寻找的正常行为,因为我不确定它是。
祝你好运。
我有一个包含两个片段的 ViewPager。一个 fragment
什么都不包含,另一个 fragment
包含 gridview
和 ImageViews
。
ImageViews
有一组 onClickListener
。
到目前为止一切正常......但是当我在什么都不包含的片段上并点击其他片段的 onClickListener 某处时,即使它的元素不可见,imagview 也会对我的点击做出反应。
我可以更改我的 onClickListener
以便它检查显示的是哪个片段,但这真的是我应该做的吗???感觉有点脏
这是我的 FragmentStatePageAdapter
public class OwnPagerAdapter extends FragmentStatePagerAdapter{
private BackgroundImage backgroundImage = new BackgroundImage();
private Apps apps = new Apps();
private Home_Screen ac;
public OwnPagerAdapter(FragmentManager fm, Home_Screen activity) {
super(fm);
this.ac = activity;
}
@Override
public Fragment getItem(int position) {
if(position == 0) {
return backgroundImage;
}else if(position == 1) {
return this.apps;
}
return null;
}
@Override
public int getCount() {
return 2;
}
}
这是我的 BaseAdapter
public class AppAdapter extends BaseAdapter {
private AppLauncher launcherListener = new AppLauncher();
private ArrayList<ApplicationInfo> appList;
private Context ctx;
public AppAdapter(ArrayList<ApplicationInfo> listOfApps, Context ctx){
this.appList = listOfApps;
this.ctx = ctx;
}
@Override
public int getCount() {
return this.appList.size();
}
@Override
public Object getItem(int i) {
ImageView v = new ImageView(this.ctx);
v.setImageDrawable(this.appList.get(i).loadIcon(this.ctx.getPackageManager()));
return v;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
if(view != null){
((ImageView) view).setImageDrawable(this.appList.get(i).loadIcon(this.ctx.getPackageManager()));
view.setTag(i);
return view;
}
ImageView v = new ImageView(this.ctx);
v.setImageDrawable(this.appList.get(i).loadIcon(this.ctx.getPackageManager()));
v.setScaleType(ImageView.ScaleType.CENTER);
v.setOnClickListener(launcherListener);
v.setTag(i);
return v;
}
private class AppLauncher implements View.OnClickListener {
@Override
public void onClick(View view) {
ctx.startActivity(ctx.getPackageManager().getLaunchIntentForPackage(appList.get((int) view.getTag()).packageName));
}
}
}
那是我的片段class
public class Apps extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<ApplicationInfo>>{
private GridView gridview;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
getLoaderManager().initLoader(1, null, this).forceLoad();
View rootView = inflater.inflate(R.layout.fragment_apps, container, false);
this.gridview = (GridView)rootView.findViewById(R.id.apptable);
return rootView;
}
@Override
public Loader<ArrayList<ApplicationInfo>> onCreateLoader(int id, Bundle args) {
return new AppLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<ArrayList<ApplicationInfo>> loader, ArrayList<ApplicationInfo> data) {
Toast.makeText(getActivity(), "Done with loading Apps", Toast.LENGTH_LONG).show();
this.gridview.setAdapter(new AppAdapter(data,getActivity()));
}
@Override
public void onLoaderReset(Loader<ArrayList<ApplicationInfo>> loader) {
}
}
虽然我找不到您问题的任何具体原因,但我必须建议一种更简洁的方法来实现您正在寻找的相同结果,使用内部 class 只是为了捕获点击事件是肮脏的,而且是不必要的.使用此方法很有可能也能解决您的问题。
为什么不在整个 gridview 上使用 OnItemClickListener,而不是使用实现 OnClickListener 然后手动为每个项目设置它的 AppLauncher class?它将处理每个项目的点击事件,并且仅特定于您的 gridview 中的项目,因此您不必像使用内部 classes 那样担心任何泄漏。
在您的片段中实现 OnItemClickListener :
public class Apps extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<ApplicationInfo>>, OnItemClickListener
然后在片段的 onCreate 中简单地将适配器设置为 gridview:
gridview.setOnItemClickListener(this);
并实施必要的方法:
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
getActivity().startActivity(getActivity().getPackageManager().getLaunchIntentForPackage(appList.get(position).packageName));
}
现在您可以从 gridview 的适配器中删除 OnClickListener 逻辑,它应该可以正常工作,我猜它也可以解决您的问题,即使不能,嘿,至少您最终会得到一个更清晰的代码。
关于您的代码,我觉得奇怪的另一件事是您覆盖了 getItemId() 但始终 return 0,请确保这是您正在寻找的正常行为,因为我不确定它是。
祝你好运。