先上一张图,看懂这张图后,才可以看下面的内容。 这张图的意思就是什么东西里面又包含了什么东西的意思,代码其实只是如何“剥”出每一层。
下面开始整代码:
把它改为线性布局,添加两个碎片,做菜单的碎片fl_menu的宽度占屏幕宽度的1/3,做内容的碎片fl_main点屏幕宽度的2/3;
注意上面是两个FrameLayout帧布局,而不是两个Fragment碎片。 用FrameLayout的原因,相当于是先做一个模板,程序启动后,还要用两个碎片把它们替换下来。
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();
//用碎片替换帧布局只能用事务处理
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()的第三个参数,第一个是被替换的布局ID,第二个是替换的对象,第三个是有待去查资料。
menuFragment.setOnDataTransmissionListener()是执行自定义的监听事件,这与Button的点击事件不一样,因为fragment不确定,所以监听什么也是不确定的,因此要自定义。 具体代码要看MenuFragment.java。
在这个碎片中添加一个ListView控件,仅此而己
为什么要加这个“额外的"XML呢?因为ListView中包含各”条目",而各条目的内部组成实际上是一个TextView.所以就用这个TextView代表所有条目的中的TextView。这个XML文件没有与它相对应的类。
/**
* 左侧的菜单Fragment
* Created by Jun&Hui on 2016/10/9.
*/
public class MenuFragment extends Fragment {
List 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 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{}是定义的一个内部接口。
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);
}
}