请记住,我是Android的初学者,所以有可能在某个地方我忽略了一些东西。此外,我还有一个问题,因为我对整个项目的态度可能是错误的。
我有一个通过DrawerLayout实现侧边菜单的应用程序。 “主屏幕”是一个片段和抽屉我创建了侧面菜单,其中包含一个列表。之后,这就是我点击侧边菜单时更改碎片的方式:
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new FavoritesFragment();
break;
case 2:
fragment = new LastVisitedFragment();
break;
case 3:
fragment = new SettingsFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
Log.e("MainActivity", "Error in creating fragment");
}
}
上面的代码在我的主要活动中实现。接下来是我的HomeFragment的外观: (主页片段是我的主页,所以说)
public class HomeFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i("HomeFragment", "OK");
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
rootView.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View v) {
Log.i("HomeFragment", "OK0");
switch (v.getId()) {
case R.id.rec_prod1:
Log.i("HomeFragment", "OK1");
Intent intent1 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent1);
break;
case R.id.rec_prod2:
Log.i("HomeFragment", "OK2");
Intent intent2 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent2);
break;
case R.id.rec_prod3:
Log.i("HomeFragment", "OK3");
Intent intent3 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent3);
break;
}
}
});
return rootView;
}
}
我已经尝试使用onTouchListener,但也没有用,唯一的区别是onTouch它进入了onTouch方法,打赌后没有发生任何事情。在这个网站的某个地方,我有红色设置scrollview clickable = true和所有childs为false,以便它可以工作,但这也没有。 fragment_home.xml也是一个自定义布局,其中Parent是一个ScrollView(它是一个包含三个颜色和5行但每个元素不同的列表,它们都有一个Imageview和不同数量的textview,我没有使用ListView或GridList因为每一行都有一个标题,每行中的元素都有不同的布局)我只附加了它的概述,因为真正的xml代码超过800行。
<ScrollView>
<LinearLayout>
<!--This part repeats 5 times creating each row -->
<TextView>
<LinearLayout>
<!-- This part repeats 3 times for each element of a column -->
<RelativeLayout>
<ImageView>
<!-- This part changes acodringly to the number of textviews, I can have 1 to 3 TextViews here-->
<LinearLayout>
<TextView>
<TexytView>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
所以我有两个主要问题。 1.为什么点击/触摸不起作用。 2.项目结构(架构)是否正常?整个想法是,当点击发生时,一些元素将我带到产品视图屏幕,而其他元素带到产品元素列表(填充所有这些的数据将来自服务器,这就是我在onClick中启动新活动的原因方法)。
答案 0 :(得分:0)
您需要通过XML设置onclick操作(这适用于活动),或者您需要在代码中设置它(几乎就像您拥有它),但是分配给视图本身
我个人更喜欢在代码中定义点击操作。我认为在阅读项目时更有意义,你可以避免任何类似的问题。它也是推荐的方法,大多数示例代码和示例都是这样做的(参见Android Documentation)
要通过代码定义点击,请执行以下操作:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
View OK3 = rootView.findViewById(R.id.rec_prod3); //pick a better name than i have though
if (OK3 != null) {
OK3.setOnClickListener(new View.OnclickListener() {
Log.i("HomeFragment", "OK3");
Intent intent3 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent3);
});
}
大多数示例使用此方法作为使用switch语句的替代方法,并且通过相同的方法指导每次单击都是不好的做法 - 实际上,您正在攻击Google为XML支持提供的快捷方式,以执行其不打算做的事情对于。有关为什么最好使用专用侦听器的更多信息,请查看继承与组合 - 作为规则&#34;有A&#34;总是节拍&#34;是A&#34;代码可读性和可维护性。
答案 1 :(得分:-1)
您正在为整个片段设置OnClickListener,而不是您在switch-statement中查询的实际视图。当然,从未达到具体的代码部分! 这种方法应该有效(并且officially supported by Google和well received by users on Stack Overflow):
public class HomeFragment extends Fragment implements View.OnClickListener {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i("HomeFragment", "OK");
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
rootView.findViewById(R.id.rec_prod1).setOnClickListener(this);
rootView.findViewById(R.id.rec_prod2).setOnClickListener(this);
rootView.findViewById(R.id.rec_prod3).setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v) {
Log.i("HomeFragment", "OK0");
switch (v.getId()) {
case R.id.rec_prod1:
Log.i("HomeFragment", "OK1");
Intent intent1 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent1);
break;
case R.id.rec_prod2:
Log.i("HomeFragment", "OK2");
Intent intent2 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent2);
break;
case R.id.rec_prod3:
Log.i("HomeFragment", "OK3");
Intent intent3 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent3);
break;
}
}
}
进一步阅读:
通过XML设置onClick也可以,但遗憾的是,只在活动中,而不是在片段中:在片段的父活动上调用该方法(参见How to handle button clicks using the XML onClick within Fragments)。
但是,上述方法还有一个缺点:onClick是公开的,因此可以从外部调用。例如,父活动可以调用
((View.OnClickListener) homeFragment).onClick(
homeFragment.getView().findViewById(R.id.rec_prod1));
这将触发rec_prod1的onClick事件。 IMO,这种方法带来的可读性和便利性超过了这一点。当然,还有其他方法各有优缺点。最重要的是,为了防止这种公共访问,您可以为每个监听器创建一个匿名类(请参阅Nick的答案和its disadvantages)或使用以下代码:
public class HomeFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i("HomeFragment", "OK");
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
View.OnClickListener onClick = new RecProdClickListener();
rootView.findViewById(R.id.rec_prod1).setOnClickListener(onClick);
rootView.findViewById(R.id.rec_prod2).setOnClickListener(onClick);
rootView.findViewById(R.id.rec_prod3).setOnClickListener(onClick);
return rootView;
}
private class RecProdClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
Log.i("HomeFragment", "OK0");
switch (v.getId()) {
case R.id.rec_prod1:
Log.i("HomeFragment", "OK1");
Intent intent1 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent1);
break;
case R.id.rec_prod2:
Log.i("HomeFragment", "OK2");
Intent intent2 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent2);
break;
case R.id.rec_prod3:
Log.i("HomeFragment", "OK3");
Intent intent3 = new Intent(getActivity(), SingleItemActivity.class);
startActivity(intent3);
break;
}
}
}
}
除了所有这些之外,几个匿名点击监听器将导致更多的内存使用和更长的初始化时间,而重复使用带有switch语句的点击监听器将使性能成为negligibly worse due to cyclomatic complexity。
但你甚至可以混合使用不同的方法。最终,这取决于您的口味。讨论在什么情况下什么是最好的属于programmers.stackexchange并且肯定是Android开发中干净代码的一个有趣话题。