安卓如何写fragment中的点击事件
先上一张图,看懂这张图后,才可以看下面的内容。 这张图的意思就是什么东西里面又包含了什么东西的意思,代码其实只是如何“剥”出每一层。
下面开始整代码:
第一步:新建一个安卓项目,它会自动生成MainActivity.java和activity_main.xml, 请不要改名字;
第二步:新建一个fragment,取名为MainFragment,它会自动生成MainFragment.java和main_fragemnt.xml,请不要做任何修改;
第三步:新建一个fragment,取名为MenuFragment,它会自动生成MenuFragment.java和menu_fragemnt.xml,请不要做任何修改;
第四步:修改activity_main.xml文件的内容为:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.jintingbo.myapplication17.MainActivity"> <FrameLayout android:id="@+id/fl_menu" android:layout_width="0dp" android:layout_weight="1" android:background="#20ff0000" android:layout_height="match_parent"/> <FrameLayout android:id="@+id/fl_main" android:layout_width="0dp" android:layout_weight="2" android:background="#2500ff00" android:layout_height="match_parent"/> </LinearLayout>
把它改为线性布局,添加两个碎片,做菜单的碎片fl_menu的宽度占屏幕宽度的1/3,做内容的碎片fl_main点屏幕宽度的2/3;
第五步:修改MainActivity.java中的文件内容为:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MenuFragment menuFragment = new MenuFragment();
final MainFragment mainFragment = new MainFragment();
//将上面的两个Fragment添加进来,用事务处理是为了能后退
getSupportFragmentManager().beginTransaction().replace(R.id.fl_menu, menuFragment, "menuFragment").commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fl_main, mainFragment, "mainFragment").commit();
menuFragment.setOnDataTransmissionListener(new MenuFragment.OnDataTransmissionListener() {
@Override
public void dataTransmission(String data) {
mainFragment.setData(data);
}
});
}
}
红色代码为新添加的,final MainFragment mainFragment = new MainFragment();为什么要加final,是因为下面的mainFragment.setData(data);必须要求mainFragmint是常量才可以运行。
getSupportFragmentManager().beginTransaction().replace(R.id.fl_menu, menuFragment, "menuFragment").commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fl_main, mainFragment, "mainFragment").commit();
这两句是将原来Activity中有的fragment全部清除后,再添加现在的menuFragment和mainFragment,它的意思是,你用哪个fragment,就把其它的全部清了,这样不干扰。 这里为什么是用事务的replace()呢?因为事务可以后退, 如果不是事务的replace()你就后退不成,因为原来fragmetn全部被清除了。
replace()的第三个参数,好像随便打一个字符串都可以。这个有待研究,有知道的请留言告之!
menuFragment.setOnDataTransmissionListener()是执行自定义的监听事件,这与Button的点击事件不一样,因为fragment不确定,所以监听什么也是不确定的,因此要自定义。 具体代码要看MenuFragment.java。
第六步:修改menu_fragemnt.xml中的内容
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/lv_menu" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
在这个碎片中添加一个ListView控件,仅此而己
第七步:在layout中新建一个menu_fragemnt_item.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_menu_item" android:layout_width="match_parent" android:gravity="center_vertical" android:textColor="#000" android:layout_height="40dp" /> </RelativeLayout>
为什么要加这个“额外的"XML呢?因为ListView中包含各”条目",而各条目的内部组成实际上是一个TextView.所以就用这个TextView代表所有条目的中的TextView。
第八步:修改MenuFragment.java为如下内容
/** * 左侧的菜单Fragment * Created by Jun&Hui on 2016/10/9. */ public class MenuFragment extends Fragment { List<String> mDatas = new ArrayList<>(); private OnDataTransmissionListener mListener; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //求碎片 View menuView = View.inflate(getActivity(), R.layout.menu_fragemnt, null); //准备显示值 mDatas.add("新闻1"); mDatas.add("新闻2"); mDatas.add("新闻3"); mDatas.add("新闻4"); mDatas.add("新闻5"); //求碎片中的ListView控件 final ListView lv = (ListView) menuView.findViewById(R.id.lv_menu); //用适配器设置显示值和求一些其它的值 lv.setAdapter(new BaseAdapter() { @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { //求条目,因为ListView中的条目与menu_fragment_item的表现形式是样 //其实就是获取menu_fragment_item.xml View contentView = LayoutInflater.from(getActivity()).inflate(R.layout.menu_fragemnt_item, parent, false); //求条目中的文本 TextView tv = (TextView) contentView.findViewById(R.id.tv_menu_item); tv.setText(mDatas.get(position)); /** * 需求:点击对应的条目,将条目的内容发送到MainFragment中的Button上,更改Button名称(即进行一个数据传递) */ lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { /** * 方法三:使用第三方开源框架EventBus */ EventBus.getDefault().post(mDatas.get(position)); } }); return contentView; } }); return menuView; } //接口回调的方法 public interface OnDataTransmissionListener { public void dataTransmission(String data); } public void setOnDataTransmissionListener(OnDataTransmissionListener mListener) { this.mListener = mListener; } }
弄懂上面的代码,基本上就把整个程序就弄懂了,下面我慢慢道来:
List<String> mDatas = new ArrayList<>(); 这一句的目的就是为了给ListView条目设置显示值的,比如第一条是新闻1,第二条是新闻2...., 下面的mDatas.add("新闻1");等几条语句就是为它设置显示值。 private OnDataTransmissionListener mListener; 这是一条事务监听对象; onCreateView()是fragmet生命周期的函数, 它是管fragment界面上的东西的; View menuView = View.inflate(getActivity(), R.layout.menu_fragemnt, null);这一句是获取Activiti中的菜单(menu_fragemnt)视图, 第一个参数getActivity()表示求本fragment的宿主。 final ListView lv = (ListView) menuView.findViewById(R.id.lv_menu);这一句表示再从上一句所求的菜单视图中求出ListView控件。 lv.setAdapter(new BaseAdapter()); 这一句表示是给ListView设置适配器,目的是要给ListView设置显示值和对ListView进行监听, 这里的适配器是使用BaseAdapter。 得到lv(lv就是ListView控件)后,还要再进一点得到其中的“条目”其它语言叫Item,这个“条目”要在 public View getView(int position, View convertView, ViewGroup parent){}中去求, View contentView = LayoutInflater.from(getActivity()).inflate(R.layout.menu_fragemnt_item, parent, false);这一句就是求条目。 TextView tv = (TextView) contentView.findViewById(R.id.tv_menu_item);这一句表示求条目中的TextView; tv.setText(mDatas.get(position));这一句表示为条目中的TextView赋值,就是在条目上显示标题。 lv.setOnItemClickListener(new AdapterView.OnItemClickListener());这一句表示ListView的监听事件;从下面的onItemClick可以看出它监听的是点击事件。 EventBus.getDefault().post(mDatas.get(position));这一句表示用EventBus框架,发送一个数据出去。 EventBus是第三方框架,在使用时要加依赖,具体位置是在build.gradle(Modul:app)中的 dependencies { ... implementation 'org.greenrobot:eventbus:3.0.0' ... } onCreateView()是返回的碎片, getView()是返回的“条目”, 后面的代码: //接口回调的方法 public interface OnDataTransmissionListener { public void dataTransmission(String data); } public void setOnDataTransmissionListener(OnDataTransmissionListener mListener) { this.mListener = mListener; } 是与MainActivity.java中的事务监听事件密切相关的。public interface OnDataTransmissionListener{}是定义的一个内部接口。
第九步:修改MainFragment.java文件的内容为:(注释都写清楚了,就不另外再解释)
public class MainFragment extends Fragment { //有一个TextView private TextView textView; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //得到主界面中的main碎片 View mainView = View.inflate(getActivity(), R.layout.main_fragemnt, null); //得到碎片中的textView textView=(TextView)mainView.findViewById(R.id.textView); //注册第三方框架 EventBus.getDefault().register(this); return mainView; } @Subscribe public void onEvent(String data) { textView.setText(data); } public void setData(String string) { textView.setText(string); } //退出时要撤销第三方框架 @Override public void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } }
最后结果: