我从一个被解析为Application
类中的对象的Web服务接收数据,这个对象在我的例子中是一个Report
类包含一个Tabs
列表填充ViewPager
。因此,此报告存储在Application类的currentReport
参数中。
每个标签应该是ViewPager
中的一个页面。因此,当我第一次收到数据并对其进行解析时,所有数据都能完美运行,并且View Pager会填充正确的数据并显示出来。
当我想从服务器获取新的Report
并使用已解析为ViewPager
参数的新数据刷新currentReport
时,我的问题就开始了。
我的ViewPager
可以刷卡并且有标签导航,所以当我尝试使用新ViewPager
重新实例化Report
时,我看到添加了适当数量的标签tabHost
。由于某种原因,新报告的片段覆盖了普通报告的片段。因此,如果新报告中的选项卡数量大于上一个报告中的选项卡,那么我可以看到上一个报告中的选项卡以及部分新选项卡(例如,在第一个报告中我有一个选项卡,以及在新的那个我有3然后我看到前一个片段和下一个片段中的最后一个片段)。
我从本教程开始我的开发并添加了smoe代码: http://thepseudocoder.wordpress.com/2011/10/13/android-tabs-viewpager-swipe-able-tabs-ftw/
这是我的Tab活动代码:
public class TabsViewPagerFragmentActivity extends FragmentActivity implements ViewPager.OnPageChangeListener, TabHost.OnTabChangeListener
{
static final String TAG = TabsViewPagerFragmentActivity.class.getSimpleName();
private TabHost mTabHost;
private ViewPager mViewPager;
private HashMap<String, TabInfo> mapTabInfo;
public ViewPagerAdapter mPagerAdapter;
private TextView tvReportName, tvTabTitle;
private Button bBackToParameters;
private Dialog progressDialog;
private SGRaportManagerAppObj application;
private int numberOfTabs = 0;
private Display display;
public static final int POPUP_MARGIN = 6;
LeftSideMenu leftSideMenu;
public void NotifyTabActivityViewPagerAdapter()
{
mPagerAdapter.notifyDataSetChanged();
}
public ViewPagerAdapter getTabActivityViewPagerAdapter()
{
return mPagerAdapter;
}
public ViewPager getTabActivityViewPager()
{
return mViewPager;
}
public void setCurrentTabTitle (String title)
{
tvTabTitle.setText(title);
Log.d(TAG, "set tab title from activity: "+title);
}
/**
* Maintains extrinsic info of a tab's construct
*/
private class TabInfo
{
private String tag;
private Class<?> clss;
private Bundle args;
private Fragment fragment;
TabInfo(String tag, Class<?> clazz, Bundle args)
{
this.tag = tag;
this.clss = clazz;
this.args = args;
}
}
/**
* A simple factory that returns dummy views to the Tabhost
*/
class TabFactory implements TabContentFactory {
private final Context mContext;
/**
* @param context
*/
public TabFactory(Context context) {
mContext = context;
}
/** (non-Javadoc)
* @see android.widget.TabHost.TabContentFactory#createTabContent(java.lang.String)
*/
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
/** (non-Javadoc)
* @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle)
*/
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
application = SGRaportManagerAppObj.getInstance();
display = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
// Inflate the layout
setContentView(R.layout.tabs_screen_activity_layout);
tvTabTitle = (TextView) findViewById(R.id.tvTabName);
tvReportName = (TextView)findViewById(R.id.tvReportName);
tvReportName.setText(application.currentReport.getName()+ " - ");
bBackToParameters = (Button) findViewById(R.id.bBackToParameters);
leftSideMenu = (LeftSideMenu) findViewById(R.id.leftSideMenu);
applyOnClickListenerToLeftSideMenu();
findViewById(R.id.showLeftMenuButton).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Display d = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = d.getWidth();
View panel = findViewById(R.id.leftSideMenu);
View appPanel = findViewById(R.id.appLayout);
if (panel.getVisibility() == View.GONE){
appPanel.setLayoutParams(new LinearLayout.LayoutParams(width, LayoutParams.FILL_PARENT));
panel.setVisibility(View.VISIBLE);
applyOnClickListenerToLeftSideMenu();
}else{
ToggleButton button = (ToggleButton) findViewById(R.id.showLeftMenuButton);
button.setChecked(false);
panel.setVisibility(View.GONE);
}
}
});
// Initialise the TabHost
progressDialog = DialogUtils.createProgressDialog(this, this.getString(R.string.populating_view_pager));
progressDialog.show();
if (SGRaportManagerAppObj.getInstance().parametersRepository.getParametersRepository().size() == 0)
{
bBackToParameters.setText(R.string.back_to_report_list);
}
this.initialiseTabHost(savedInstanceState);
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); //set the tab as per the saved state
}
// Intialise ViewPager
this.intialiseViewPager();
progressDialog.dismiss();
}
/** (non-Javadoc)
* @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle)
*/
protected void onSaveInstanceState(Bundle outState) {
outState.putString("tab", mTabHost.getCurrentTabTag()); //save the tab selected
super.onSaveInstanceState(outState);
}
/**
* Initialise ViewPager
*/
public void intialiseViewPager()
{
List<Fragment> fragments = new Vector<Fragment>();
// TabInfo tabInfo = null;
if (application.getCurrentDataSource().equals(DataSource.SSRS))
{
numberOfTabs = application.currentReport.getTabsList().size();
}
else if (application.getCurrentDataSource().equals(DataSource.SGRDL))
{
numberOfTabs = application.currentReport.getODTabsList().size();
Log.d(TAG, "CURRENT REPORT FROM VIEW PAGER: "+ application.currentReport.toString());
}
Log.d(TAG,"Current Tabs number from TabsViewPager activity: " +numberOfTabs);
if (application.getCurrentDataSource().equals(DataSource.SSRS))
{
for (int i = 0; i < numberOfTabs; i++)
{
Tab tempTab = application.currentReport.getTabsList().get(i);
if (tempTab.getTabTemplateId() == 7)
{
GridFragment gridFragment = new GridFragment(tempTab);
fragments.add(gridFragment);
}
else if (tempTab.getTabTemplateId() == 8)
{
NewChartFragment chartFragment = new NewChartFragment(tempTab, this);
fragments.add(chartFragment);
}
}
}
else if (application.getCurrentDataSource().equals(DataSource.SGRDL))
{
for (int i = 0; i < numberOfTabs; i++)
{
ODTab tempTab = application.currentReport.getODTabsList().get(i);
if (tempTab.getTabType().equals(ODGrid.XML_GRID_ELEMENT))
{
GridFragment gridFragment = GridFragment.newInstance(tempTab.getTabId());
fragments.add(gridFragment);
}
else if (tempTab.getTabType().equals(ODChart.XML_CHART_ELEMENT))
{
NewChartFragment chartFragment = NewChartFragment.newInstance(tempTab.getTabId());
fragments.add(chartFragment);
}
}
}
Log.d(TAG, "Current report fragments set to adapter: "+fragments.toString());
/*
if (this.mPagerAdapter == null)
{
this.mPagerAdapter = new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
}
else
{
this.mPagerAdapter.removeAllFragments();
this.mPagerAdapter.addFragmentsListToAdapter(fragments);
}
*/
this.mPagerAdapter = new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
this.mViewPager = (ViewPager)super.findViewById(R.id.pager);
// this.mViewPager.setAdapter(null);
this.mViewPager.setAdapter(this.mPagerAdapter);
this.mViewPager.setOffscreenPageLimit(0);
this.mViewPager.setOnPageChangeListener(this);
Log.d(TAG, "Adapter initialized!");
}
/**
* Initialise the Tab Host
*/
public void initialiseTabHost(Bundle args) {
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
/*
//new edit
if (mTabHost.getChildCount() > 0)
{
mTabHost.removeAllViews();
}
*/
mTabHost.setup();
TabInfo tabInfo = null;
mapTabInfo = new HashMap<String, TabsViewPagerFragmentActivity.TabInfo>();
if (args != null)
{}
else
{
if (application.getCurrentDataSource().equals(DataSource.SSRS))
{
int numberOfTabs = application.currentReport.getTabsList().size();
for (int i = 0; i < numberOfTabs; i++)
{
Tab tempTab = application.currentReport.getTabsList().get(i);
if (tempTab.getTabTemplateId() == 7)
{
//GridFragment gridFragment = new GridFragment(tempTab);
TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab "+String.valueOf(i)).setIndicator("Tab "+String.valueOf(i)), ( tabInfo = new TabInfo("Tab "+String.valueOf(i), GridFragment.class, args)));
this.mapTabInfo.put(tabInfo.tag, tabInfo);
}
else if (tempTab.getTabTemplateId() == 8)
{
TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab "+String.valueOf(i)).setIndicator("Tab "+String.valueOf(i)), ( tabInfo = new TabInfo("Tab "+String.valueOf(i), NewChartFragment.class, args)));
this.mapTabInfo.put(tabInfo.tag, tabInfo);
}
}
}
else if (application.getCurrentDataSource().equals(DataSource.SGRDL))
{
int numberOfTabs = application.currentReport.getODTabsList().size();
for (int i = 0; i < numberOfTabs; i++)
{
ODTab tempTab = application.currentReport.getODTabsList().get(i);
// Log.d(TAG,"Crashed Tab type: "+ tempTab.getTabType());
if (tempTab.getTabType().equals(ODGrid.XML_GRID_ELEMENT))
{
//GridFragment gridFragment = new GridFragment(tempTab);
TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab "+String.valueOf(i)).setIndicator("Tab "+String.valueOf(i)), ( tabInfo = new TabInfo("Tab "+String.valueOf(i), GridFragment.class, args)));
this.mapTabInfo.put(tabInfo.tag, tabInfo);
}
else if (tempTab.getTabType().equals(ODChart.XML_CHART_ELEMENT))
{
TabsViewPagerFragmentActivity.AddTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab "+String.valueOf(i)).setIndicator("Tab "+String.valueOf(i)), ( tabInfo = new TabInfo("Tab "+String.valueOf(i), NewChartFragment.class, args)));
this.mapTabInfo.put(tabInfo.tag, tabInfo);
}
}
}
}
// Default to first tab
//this.onTabChanged("Tab1");
//
mTabHost.setOnTabChangedListener(this);
}
/**
* Add Tab content to the Tabhost
* @param activity
* @param tabHost
* @param tabSpec
* @param clss
* @param args
*/
private static void AddTab(TabsViewPagerFragmentActivity activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo)
{
// Attach a Tab view factory to the spec
ImageView indicator = new ImageView(activity.getBaseContext());
indicator.setPadding(10, 10, 10, 10);
indicator.setImageResource(R.drawable.tab_select_icon_selector);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(10, 10, 10, 10);
indicator.setLayoutParams(lp);
tabSpec.setIndicator(indicator);
tabSpec.setContent(activity.new TabFactory(activity));
tabHost.addTab(tabSpec);
}
/** (non-Javadoc)
* @see android.widget.TabHost.OnTabChangeListener#onTabChanged(java.lang.String)
*/
public void onTabChanged(String tag) {
//TabInfo newTab = this.mapTabInfo.get(tag);
int pos = this.mTabHost.getCurrentTab();
this.mViewPager.setCurrentItem(pos);
}
/* (non-Javadoc)
* @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrolled(int, float, int)
*/
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageSelected(int)
*/
@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
this.mTabHost.setCurrentTab(position);
}
/* (non-Javadoc)
* @see android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrollStateChanged(int)
*/
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
这是我的适配器代码:
public class ViewPagerAdapter extends FragmentPagerAdapter
{
private List<Fragment> fragments;
/**
* @param fm
* @param fragments
*/
public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
/* (non-Javadoc)
* @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
*/
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
/* (non-Javadoc)
* @see android.support.v4.view.PagerAdapter#getCount()
*/
@Override
public int getCount() {
return this.fragments.size();
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
我的AsyncTask解析数据并更新了ViewPager:
public class ParseSGRDLReportDataAsyncTask extends AsyncTask<String, Object, Report>{
static final String TAG = ParseSGRDLReportDataAsyncTask.class.getSimpleName();
private Activity activity;
private Exception exception;
private ResponseHandler responseHandler = new ResponseHandler();
private SGRaportManagerAppObj application;
private Dialog progressDialog;
public ParseSGRDLReportDataAsyncTask(LoginScrActivity activity) {
super();
this.activity = activity;
}
public ParseSGRDLReportDataAsyncTask(Activity currentActivity) {
super();
this.activity = currentActivity;
}
public void onPreExecute() {
application = SGRaportManagerAppObj.getInstance();
progressDialog = DialogUtils.createProgressDialog(activity, activity.getString(R.string.parse_data_dialog_message));
progressDialog.show();
}
@Override
protected Report doInBackground(String... params) {
String ReportDataString = params[0];
try{
return DataAccessManager.parseSGRDLReportData(ReportDataString);
}
catch (Exception e) {
exception = e;
return null;
}
}
@Override
public void onPostExecute(Report result) {
progressDialog.dismiss();
if (exception == null)
{
if (activity.getClass() == TabsViewPagerFragmentActivity.class)
{
application.currentReport = result;
Log.d(TAG, "Current report parsed is: "+result);
((TabsViewPagerFragmentActivity)activity).intialiseViewPager();
((TabsViewPagerFragmentActivity)activity).initialiseTabHost(null);
((TabsViewPagerFragmentActivity)activity).NotifyTabActivityViewPagerAdapter();
}
else
{
responseHandler.handleProcessSGRDLReportDataResult(result, activity);
}
}
else {
processException();
}
}
private void processException() {
Toast.makeText(activity, activity.getString(R.string.error_when_parsing_data), 3000).show();
}
}
答案: 对于遇到同样问题的所有人的 @Luksprog 建议,这是对我有用的最终结果,在我需要添加的AsyncTask中:
if (activity.getClass() == TabsViewPagerFragmentActivity.class)
{
TabsViewPagerFragmentActivity tempActivity = ((TabsViewPagerFragmentActivity)activity);
application.currentReport = result;
Log.d(TAG, "Current report parsed is: "+result);
List<Fragment> frags = tempActivity.getTabActivityViewPagerAdapter().getFragments(); // getter method in your adapter
FragmentTransaction ft = tempActivity.getSupportFragmentManager().beginTransaction();
for (int i = 0; i < frags.size(); i++)
{
ft.remove(frags.get(i));
}
ft.commit();
tempActivity.intialiseViewPager();
tempActivity.getTabHost().getTabWidget().removeAllViews();
tempActivity.initialiseTabHost(null);
tempActivity.NotifyTabActivityViewPagerAdapter();
}
当主要的两点是使用FragmentManager
从SupportFragmentManager
/ FragmentTransaction
移除之前添加的片段,以在ViewPager
中显示正确的片段集合在添加新视图之前删除TabWidget
中的所有视图。
答案 0 :(得分:5)
我不确定你是否解决了这个问题,如果是的话,请忽略我的答案。 Neron T
提供的链接很重要(更重要的是,那里的建议不能引用外部适配器的片段)。
当您第二次使用新数据设置适配器时,由于FragmentPagerAdapter
的实现方式,您将继续看到旧片段。当您再次设置适配器时,适配器将首先运行destroyItem()
方法,其中的片段将从ViewPager
分离。接下来,适配器将运行instantiateItem()
方法。在此方法中,将对FragmentManager
执行检查,以查看是否仍有任何先前的片段可用。这个检查将找到旧的碎片(至少对于旧的位置,这就是为什么你得到新的碎片位置,而不是之前的情况,那时没有任何碎片)因为它们只是从{ {1}}(但仍可在ViewPager
到FragmentManager
中使用)。如果仅在findFragmentByTag()
中找不到片段,则会调用FragmentManager
方法,从列表中检索片段。
您应该修改代码以删除对这些片段的列表引用,还有其他ways to retrieve the fragments from the ViewPager
(也不是很理想)。作为快速修复,您可以尝试从getItem()
手动删除旧片段(在设置新适配器之前)以强制FragmentManager
方法始终调用ViewPager.instantiateItem()
:
getItem()
未经测试,请尝试查看是否有效。
答案 1 :(得分:4)
此问题有两种解决方案:
解决方案1 - 简单的 见这里:https://stackoverflow.com/a/13467232/444324
基本上您需要将此代码添加到viewpager适配器:
@Override
public int getItemPosition(Object object){
return PagerAdapter.POSITION_NONE;
}
解决方案2 - 推荐的在这里得到了很好的解释:https://stackoverflow.com/a/8024557/444324
答案 2 :(得分:1)
我将发布一些代码,以便您了解一下。
适配器初始化并设置将其添加到view-pager。
vfPageContainer = (ViewPager)findViewById(R.id.vfPageContainer);
mAdapter = new TestFragmentAdapter(this,getSupportFragmentManager());
vfPageContainer.setAdapter(mAdapter);
每次新数据出现时我都会调用以下方法:
updateUi()方法
private void updateUi()
{
for(int i=0 ; i < alDataPages.size() ; i++)
{
mAdapter.addFragment(TestFragment.newInstance(this));
}
mAdapter.notifyDataSetChanged();
}
在TestFragmentAdapter类中,有一些方法可以添加和清除view-pager中的片段。
TestFragmentAdapter类
class TestFragmentAdapter extends FragmentStatePagerAdapter {
private Context context;
private ArrayList<Fragment> views = new ArrayList<Fragment>();
public TestFragmentAdapter(Context context,FragmentManager fm)
{
super(fm);
this.context = context;
views = new ArrayList<Fragment>();
}
@Override
public Fragment getItem(int position)
{
return views.get(position);
}
public void addFragment (Fragment v)
{
views.add(v);
}
public void clear()
{
for(int i = 0 ; i < views.size() ; i++)
{
views.clear();
}
}
@Override
public int getCount()
{
return views.size();
}
}
TestFragment类
public final static class TestFragment extends Fragment {
private Context context;
public void setContext(Context c)
{
context = c;
}
public static TestFragment newInstance(Context context)
{
TestFragment f = new TestFragment();
f.setContext(context);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
WebView webView_viewpage = new WebView(context);
return webView_viewpage;
}
}
所以当新数据出现之前我会调用下面的代码。 我正在从适配器删除所有视图并创建新的1,并且每次都将其设置为view-pager。您还应该在代码中尝试使用它。
mAdapter.clear(); // previously it was not working so i created new adapter and set it to the viewpager.
mAdapter = new TestFragmentAdapter(this,getSupportFragmentManager());
vfPageContainer.setAdapter(mAdapter);
希望对您有所帮助,您将找到解决方案。