Fragment 我们大家经常用的一个“碎片”控件,在fragment的切换中我们会用到hide(),show()方法,当然了这只是fragment之间切换的一种方法,今天我们我们不讲fragment是怎么切换的,而是谈谈fragment中的onHiddenChanged()方法。
最近我在项目中遇到一个对于新手(也包括我啊)来说比较蛋疼的BUG,先看一下问题所在,然后我在讲解。
大家发现问题所在了吗? “工作”,“应用”,“统计”,“我的”,这四个模块都是fragment页面,在“统计”页面中又有“同事”,“我的”两个fragment组成,而在每一个页面中都会有一个popupwindow弹出,(这个popupwindow是我自定义的,之中设置了setOutsideTouchable(false),后面会有详细介绍),当我切换“同事”,“我的”两个fragment时,popupwindow会消失,点击列表进去日志页面时也会消失,点击空白处不会消失,(这些都没问题),但是当我切换 “工作”,“应用”,“统计”,“我的”四个fragment时,popupwindow不会消失(问题所在),这是为什么呢?
当我切换“同事”,“我的”两个fragment时,popupwindow会消失。是因为我在“同事”,“我的”两个fragment中分别设置了:
@Override
public void onPause() {
super.onPause();
if (timeChoosePopupWindow.isShowing()){
timeChoosePopupWindow.dismiss();
}
}
点击空白处不会消失
setOutsideTouchable(false)
好了!我们先看一下,popupwindow:
/**
* 任务列表中的时间筛选
*/
public class TimeChoosePopupWindow extends PopupWindow{
private View conentView;
private Activity activity;
private TextView tv_start;
private TextView tv_end;
private Button bt_submit;
private TimePickerView timePickerView;
private String time_start ;
private String time_end ;
private Boolean isEndTime = false;//判断选择的是开始时间还是结束时间
private LinearLayout ll_content;
public TimeChoosePopupWindow(Activity activity) {
this.activity = activity;
initView();
setOutsideTouchable(false);
}
@Override
public void showAsDropDown(View anchor) {
setAnimationStyle(R.anim.bottom_enter); //PopupWindow 显示 的动画效果
super.showAsDropDown(anchor);
}
@Override
public void dismiss() {
setAnimationStyle(R.anim.bottom_exit);//PopupWindow 消失 的动画效果
super.dismiss();
}
private void initView(){
initTimePickerView();
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
conentView = inflater.inflate(R.layout.popup_time_choose, null);
tv_start = (TextView) conentView.findViewById(R.id.tv_start);
ll_content = (LinearLayout) conentView.findViewById(R.id.ll_content);
tv_end = (TextView) conentView.findViewById(R.id.tv_end);
bt_submit = (Button) conentView.findViewById(R.id.bt_submit);
time_start = DateUtils.currentYM() + "-01";
time_end = DateUtils.currentYMD();
tv_start.setText(time_start);//起始时间为当月1号
tv_end.setText(time_end); //结束时间为本月当天`
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
setContentView(conentView);
tv_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isEndTime = false;
timePickerView.setTime(DateUtils.Str2DateYMD(time_start));
timePickerView.show();
ll_content.setVisibility(View.VISIBLE);
}
});
tv_end.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
isEndTime = true;
timePickerView.setTime(DateUtils.Str2DateYMD(time_end));
timePickerView.show();
ll_content.setVisibility(View.VISIBLE);
}
});
bt_submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//确定
if (onClickSureListener != null){
onClickSureListener.clickSure(time_start,time_end);
}else {
Log.d("-----", "onClick() returned: " + "onClickSureListener == null");
}
}
});
}
/**
* 初始化时间选择器
*/
private void initTimePickerView(){
timePickerView = new TimePickerView(activity, TimePickerView.Type.YEAR_MONTH_DAY);
//控制时间范围
Calendar calendar = Calendar.getInstance();
timePickerView.setRange(calendar.get(Calendar.YEAR) - 20, calendar.get(Calendar.YEAR) + 20);//要在setTime 之前才有效果哦
timePickerView.setCyclic(true);
timePickerView.setTime(new Date());
timePickerView.setCancelable(false);
timePickerView.setOnTimeSelectListener(new TimePickerView.OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date) {
if (!isEndTime){
//开始时间
time_start = DateUtils.getTimeYMD(date);
tv_start.setText(time_start);
}else {
//结束时间
time_end = DateUtils.getTimeYMD(date);
tv_end.setText(time_end);
}
}
});
timePickerView.setOnDismissListener(new com.bigkoo.pickerview.listener.OnDismissListener() {
@Override
public void onDismiss(Object o) {
ll_content.setVisibility(View.GONE);
}
});
}
//自定义点击确定接口
public interface OnClickSureListener{
void clickSure(String startTime,String endTime);
}
private OnClickSureListener onClickSureListener;
public void setOnClickSureListener(OnClickSureListener onClickSureListener) {
this.onClickSureListener = onClickSureListener;
}
/**
* 展示popupwindow
* @param view
* @param time_start
* @param time_end
*/
public void showAsDropDown_My(View view,String time_start,String time_end){
this.time_start = time_start;
this.time_end = time_end;
tv_start.setText(time_start);
tv_end.setText(time_end);
showAsDropDown(view);
}
//学习模仿写接口
public interface OnClickCancleListener{
//如果有取消按钮,参数就是点击取消(目的:传数据/跳转)时所需要的参数
void clickCancle(String timeStart, String timeEnd);
}
private OnClickCancleListener onClickCancleListener;
public void setOnClickCancleListener(OnClickCancleListener onClickCancleListener){
this.onClickCancleListener = onClickCancleListener;
}
}
具体的popupwindow实现我就不解释了,我们只针对这个问题讲解。
然后我就想把popupwindow设置为点击外部可以取消,来解决这个问题:
public TimeChoosePopupWindow(Activity activity) {
this.activity = activity;
initView();
setOutsideTouchable(true);
setFocusable(true);
setBackgroundDrawable(new BitmapDrawable());
}
大家来看一下效果:
怎么样,大家是不是认为问题解决了,哈哈哈!!!,告诉你,还远远没有,我们再看下接下来的效果你就知道问题所在了:
发现了吗?我们本来的需求是:点击日期选择栏弹出日期选择器的popupwindow,然后我们选择日期,改变日期选择栏的日期并进行查询,但是现在我们选择日期是点击的话,popupwindow就会消失,为什么呢?
其实我们一开始就进入了误区,并不是popupwindow点击外部是否消失的问题,也不是点击“同事”,“我的”切换时焦点获取的问题,而是 “统计”与“工作”这三个fragment在切换时 hide(),show ()时 ,“统计”模块中“同事”,“我的”两个模块的fragment的焦点获取的问题。然后我们在 “统计”的页面中加入onHiddenChanged()的方法来切换焦点:
/**
* Created by 李金伟 on 2017/5/2.
* 统计
*/
public class StatisticsFragment extends BaseFragment {
private ImageView iv_back;
private TextView tv_colleague;
private ImageView iv_colleague_line;
private RelativeLayout rv_colleague;
private TextView tv_my;
private ImageView iv_my_line;
private RelativeLayout rv_my;
private FrameLayout fl_statistics_content;
private FragmentManager fragmentManager;
private FragmentTransaction beginTransaction;
private OA_StatisticColleagueFragment oa_statisticcolleaguefragment;
private OA_StatisticMyFragment oa_statisticmyfragment;
private Fragment currentFragment;
@Override
public int getLayoutResId() {
return R.layout.fragment_statistics;
}
@Override
public void initView(View view) {
iv_back = (ImageView) view.findViewById(R.id.iv_back);
tv_colleague = (TextView) view.findViewById(R.id.tv_colleague);
iv_colleague_line = (ImageView) view.findViewById(R.id.iv_colleague_line);
rv_colleague = (RelativeLayout) view.findViewById(R.id.rv_colleague);
tv_my = (TextView) view.findViewById(R.id.tv_my);
iv_my_line = (ImageView) view.findViewById(R.id.iv_my_line);
rv_my = (RelativeLayout) view.findViewById(R.id.rv_my);
fl_statistics_content = (FrameLayout) view.findViewById(R.id.fl_statistics_content);
// 获取FragmentManager管理者
fragmentManager = getActivity().getSupportFragmentManager();
// 开启事务
beginTransaction = fragmentManager.beginTransaction();
if (oa_statisticcolleaguefragment == null) {
oa_statisticcolleaguefragment = new OA_StatisticColleagueFragment();
tv_colleague.setSelected(true);
tv_my.setSelected(false);
iv_colleague_line.setVisibility(View.VISIBLE);
iv_my_line.setVisibility(View.INVISIBLE);
}
currentFragment = oa_statisticcolleaguefragment;
// 添加事务
beginTransaction.add(R.id.fl_statistics_content, oa_statisticcolleaguefragment);
beginTransaction.commit();
}
@Override
public void initListener() {
rv_colleague.setOnClickListener(this);
rv_my.setOnClickListener(this);
iv_back.setOnClickListener(this);
}
@Override
public void initData() {
}
@Override
public void onClick(View view) {
// 开启事务
FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
switch (view.getId()) {
case R.id.iv_back:
//点击返回
getActivity().finish();
break;
case R.id.rv_colleague:
tv_colleague.setSelected(true);
tv_my.setSelected(false);
iv_colleague_line.setVisibility(View.VISIBLE);
iv_my_line.setVisibility(View.INVISIBLE);
if (oa_statisticcolleaguefragment == null) {
oa_statisticcolleaguefragment = new OA_StatisticColleagueFragment();
}
currentFragment = oa_statisticcolleaguefragment;
// 替换事务 同事
beginTransaction.replace(R.id.fl_statistics_content, oa_statisticcolleaguefragment);
beginTransaction.commit();
break;
case R.id.rv_my:
tv_colleague.setSelected(false);
tv_my.setSelected(true);
iv_colleague_line.setVisibility(View.INVISIBLE);
iv_my_line.setVisibility(View.VISIBLE);
if (oa_statisticmyfragment == null) {
oa_statisticmyfragment = new OA_StatisticMyFragment();
}
currentFragment= oa_statisticmyfragment;
// 替换事务 我的
beginTransaction.replace(R.id.fl_statistics_content, oa_statisticmyfragment);
beginTransaction.commit();
break;
}
}
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden){
currentFragment.onPause();
}else {
currentFragment.onResume();
}
}
}
这样问题就解决了,我们看下效果:
public final boolean isHidden() 总结:
如果该Fragment对象已经被隐藏,那么它返回true。默认情况下,Fragment是被显示的。能够用onHiddenChanged(boolean)回调方法获取该Fragment对象状态的改变,要注意的是隐藏状态与其他状态是正交的---也就是说,要把该Fragment对象显示给用户,Fragment对象必须是被启动并不被隐藏。
OK! 小伙伴们,这篇文章是根据我自己遇到的问题所写,还很不全面,只是针对问题而已,如果你有不明白的,还请留言哦!