您的位置:首页 > 其它

FragmentTabHost、Viewpager、Fragment使用过程中白屏问题及解决

2017-12-12 15:55 701 查看
关于FragmentTabHost的简单使用,我之前博客已经有提及了。这里不做多余介绍了。有需要的请看

http://blog.csdn.net/u014620028/article/details/51253031


说明:

这里我会按照:提出需求-完成功能-出现问题-解决问题。这样的流程来展示和解决问题。请按顺序完。以便更好的理解。

如果想直接看最后的解决方法,请看最后的代码就行。

需求1:启动APP,打开主界面。主界面分3个模块:一、二、三。点击切换。

代码如下:

FragmentDemo\app\src\main\res\values\styles.xml

<style name="FragmentTabHost_RadioGroup_Bottom_Style">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:gravity">center</item>
<item name="android:textSize">10sp</item>
<item name="android:button">@null</item>
<item name="android:textColor">#000000</item>
<item name="android:drawableTop">@mipmap/ic_launcher</item>
</style>


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<LinearLayout
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
</LinearLayout>

<android.support.v4.app.FragmentTabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="gone">

<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout
android:id="@+id/fragment_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
</LinearLayout>
</FrameLayout>
</android.support.v4.app.FragmentTabHost>

<LinearLayout
android:id="@+id/main_bottom_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00000000"
android:gravity="center"
android:orientation="vertical">

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#DADADA"/>

<RadioGroup
android:id="@+id/radioGroup1"
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp">

<RadioButton
android:id="@+id/rb_1"
style="@style/FragmentTabHost_RadioGroup_Bottom_Style"
android:checked="true"
android:drawableTop="@mipmap/ic_launcher"
android:text="一"
/>

<RadioButton
android:id="@+id/rb_2"
style="@style/FragmentTabHost_RadioGroup_Bottom_Style"
android:drawableTop="@mipmap/ic_launcher"
android:text="二"
/>

<RadioButton
android:id="@+id/rb_3"
style="@style/FragmentTabHost_RadioGroup_Bottom_Style"
android:drawableTop="@mipmap/ic_launcher"
android:text="三"
/>

</RadioGroup>
</LinearLayout>
</LinearLayout>


demo_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/fragment_tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="20sp"
/>

</LinearLayout>


布局相关已经完成。代码中使用

Fragment_1

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class Fragment_1 extends Fragment {

private View view;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.demo_fragment, container, false);

TextView tv = view.findViewById(R.id.fragment_tv);
tv.setText("第1个Fragment");

return view;
}

}


Fragment_2和Fragment_3同Fragment_1,引用的布局文件也一样,区别就是tv设置的文字改变一下

MainActivity

package com.chen.demo;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.widget.RadioGroup;
import android.widget.TabHost;

public class MainActivity extends FragmentActivity implements RadioGroup.OnCheckedChangeListener {

private FragmentTabHost mTabHost;

private RadioGroup mMainGroup;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

// 设置显示的标题
TabHost.TabSpec tabSpecA = mTabHost.newTabSpec("0").setIndicator("A");
TabHost.TabSpec tabSpecB = mTabHost.newTabSpec("1").setIndicator("B");
TabHost.TabSpec tabSpecC = mTabHost.newTabSpec("2").setIndicator("C");

// 添加对象
mTabHost.addTab(tabSpecA, Fragment_1.class, null);
mTabHost.addTab(tabSpecB, Fragment_2.class, null);
mTabHost.addTab(tabSpecC, Fragment_3.class, null);

mMainGroup = (RadioGroup) findViewById(R.id.radioGroup1);
mMainGroup.setOnCheckedChangeListener(this);

}

@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_1:
mTabHost.setCurrentTabByTag("0");
break;
case R.id.rb_2:
mTabHost.setCurrentTabByTag("1");
break;
case R.id.rb_3:
mTabHost.setCurrentTabByTag("2");
break;
default:
break;
}
}
}


OK,需求完成了,运行一下,效果如下:



来回切换,没有任何问题。

需求二:现在,产品要改东西了。第一个界面是主界面,要做的炫一点。改成“动态”、“话题”样式。可以左右滑动切换界面。其他不变。

要切换界面,还是支持滑动。貌似唯一的选择的就是viewpager了。

注:这里有2种方法:把LayoutInflater通过inflate转成的布局放到一个集合中,然后viewpager的adapter中对应切换。第二种方法,就是写2个Fragment,放到集合中,然后viewpager的adapter中对应切换。

我这里用第二种方法,第一种,请自行尝试。我没有试过,不做任何评价。

现在,创建2个Fragment,动态和话题。

dynamic_fragment_layout.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#55ff0000"
android:padding="5dp"
android:text="动态"
android:textSize="30sp"/>

</RelativeLayout>


topic_fragment_layout.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#5500ff00"
android:padding="5dp"
android:text="话题"
android:textSize="30sp"/>

</RelativeLayout>


DynamicFragment 动态Fragment

package com.chen.demo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class DynamicFragment extends Fragment {

private View view;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.dynamic_fragment_layout, container, false);

return view;
}

}


TopicFragment 话题Fragment

package com.chen.demo;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class TopicFragment extends Fragment {

private View view;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.topic_fragment_layout, container, false);

return view;
}

}


接下来,仅仅需要修改第一个Fragment就好了。新的第一个Fragment_1源码如下

package com.chen.demo;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

public class Fragment_1 extends Fragment implements ViewPager.OnPageChangeListener {

private View view;

private Context context;

private ViewPager dynamic_topic_viewPager;

private ArrayList<Fragment> fragmentList;

private DynamicFragment dynamicFragment;
private TopicFragment topicFragment;

private DynamicTopicFragmentPagerAdapter adapter;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_layout, container, false);

context = getActivity();
Log.e("context==", context + "");

dynamic_topic_viewPager = view.findViewById(R.id.dynamic_topic_viewPager);

fragmentList = new ArrayList<>();
dynamicFragment = new DynamicFragment();
topicFragment = new TopicFragment();

fragmentList.add(dynamicFragment);
fragmentList.add(topicFragment);

adapter = new DynamicTopicFragmentPagerAdapter(((FragmentActivity) context).getSupportFragmentManager(), fragmentList);

//去掉滑动到边缘处,继续滑动时,出现的阴影
dynamic_topic_viewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
dynamic_topic_viewPager.setAdapter(adapter);
dynamic_topic_viewPager.setCurrentItem(0);
dynamic_topic_viewPager.addOnPageChangeListener(this);

return view;
}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {

Log.e("position==", position + "");

}

@Override
public void onPageScrollStateChanged(int state) {

}

private class DynamicTopicFragmentPagerAdapter extends FragmentStatePagerAdapter {

ArrayList<Fragment> list;

public DynamicTopicFragmentPagerAdapter(FragmentManager fm, ArrayList<Fragment> list) {
super(fm);
this.list = list;
}

@Override
public Fragment getItem(int position) {

return list.get(position);
}

@Override
public int getCount() {
return list.size();
}
}

}


这个时候,启动APP,正常,第一个Fragment可以左右滑动,分别展示动态和话题内容,点击其他按钮,也可以跳转,但是,去了其他界面然后再点击底部的“一”按钮,回到第一个Fragment,白屏了。但是在白屏上左右滑动的时候,可以从onPageSelected中的那句打印看出来,界面确实切换了,但是就是不显示任何内容。

经过查资料,终于找到了解决方法

在第一个Fragment中添加一段代码

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null) {
parent.removeView(view);
}
return view;
}

view = inflater.inflate(R.layout.fragment_layout, container, false);

......
......

return view;
}


这样,就可以了。随便滑动,随便切换。回来以后,界面还在。完全没问题了

=========================================

以下内容请认真阅读

以上代码,在一些手机上,还是会出现白屏,复现步骤:

启动APP,打开动态或者话题界面,home键退到后台,尽可能多的打开手机上的应用(不管是系统自带的还是自己后来安装的),然后停一会,后台应该会把APP回收了,通过菜单键重新切换回APP中,发现白屏了。

解决方法:

在第一个Fragment中的viewpager初始化的时候,改成

adapter = new DynamicTopicFragmentPagerAdapter(getChildFragmentManager(), fragmentList);


测试手机:

华为 EVA-AL00 后台开启应用18个

小米 MI 4LTE 后台开启应用22个
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐