如何以编程方式通过 Main Activity 在 ViewPager 中更新刷新片段
Posted
技术标签:
【中文标题】如何以编程方式通过 Main Activity 在 ViewPager 中更新刷新片段【英文标题】:How to update-refresh Fragment in ViewPager by Main Activity programmatically 【发布时间】:2013-11-13 16:28:59 【问题描述】:我正在构建一个使用 Fragment 和单个 MainActivity
的应用程序,该应用程序在同一个 ViewPager 中显示不同的 Fragment 以复制典型 MVC 应用程序的行为。
问题是我不明白如何以编程方式更新片段以使用新的片段更改更新ViewPager
例如,我有一个显示图表的Fragment
,(在我的意图中)当我从主调用setFragment(int interval, Point[] snodePoint)
时,图表应该在ViewPager
中更新
public class LineFragment extends Fragment
static int interval;
static Point snodePoints[];
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
final View v = inflater.inflate(R.layout.fragment_linegraph, container,
false);
Bundle bundle = this.getArguments();
ChartConfig cg = bundle.getParcelable("FragmentData");
snodePoints = cg.getPoints();
interval= cg.getInterval();
Line l = new Line();
for(int i=0; i<snodePoints.length; i++)
LinePoint p = new LinePoint();
Point sp=snodePoints[i];
p.setX(sp.getX());
p.setY(sp.getY());
l.addPoint(p)
l.setColor(getResources().getColor(R.color.green));
LineGraph li = (LineGraph) v.findViewById(R.id.linegraph);
li.addLine(l);
li.setRangeY(0, interval);
li.setLineToFill(0);
li.setOnPointClickedListener(new OnPointClickedListener()
@Override
public void onClick(int lineIndex, int pointIndex)
// TODO Auto-generated method stub
);
return v;
简而言之,我需要
1-根据主要活动接收到的数据创建一个片段。 2-每次在主要活动发生时更改片段的数据 类似于 setFragment(...) 的新数据(始终由主生成)。我该怎么做?
带有 FragmentAdapter 的主要活动
public class MainActivity extends FragmentActivity
ViewPager mViewPager;
MyFragmentAdapter mMyFragmentAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
final ActionBar bar = this.getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
LineFragment lineFrag = new LineFragment();
BarFragment barFrag = new BarFragment();
PieFragment pieFrag = new PieFragment();
mMyFragmentAdapter = new MyFragmentAdapter(this, mViewPager);
mMyFragmentAdapter.addTab(bar.newTab().setText("Line"), LineFragment.class,
null, lineFrag);
mMyFragmentAdapter.addTab(bar.newTab().setText("Bar"), BarFragment.class,
null, barFrag);
mMyFragmentAdapter.addTab(bar.newTab().setText("Pie"), PieFragment.class,
null, pieFrag);
mViewPager.setOffscreenPageLimit(mMyFragmentAdapter.getCount() - 1);
public static class MyFragmentAdapter extends FragmentStatePagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener
private final MainActivity mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
private final ArrayList<Fragment> mFrag = new ArrayList<Fragment>();
static final class TabInfo
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args)
clss = _class;
args = _args;
public MyFragmentAdapter(MainActivity activity, ViewPager pager)
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args,
Fragment frag)
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mFrag.add(frag);
mActionBar.addTab(tab);
notifyDataSetChanged();
@Override
public int getCount()
return mTabs.size();
@Override
public Fragment getItem(int position)
TabInfo info = mTabs.get(position);
Bundle args = new Bundle();
ChartConfig cg = new ChartConfig(interval, snodePoint);
args.putParcelable("FragmentData", cg);
Fragment f = mFrag.get(position);
f.setArguments(args);
return f;
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels)
@Override
public void onPageSelected(int position)
mActionBar.setSelectedNavigationItem(position);
@Override
public void onPageScrollStateChanged(int state)
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft)
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++)
if (mTabs.get(i) == tag)
mViewPager.setCurrentItem(i);
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft)
@Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft)
我第一次创建片段时,主要活动通过覆盖的getItem(int position)
成功将参数传递给片段,但是如果我尝试更改数据,如果我尝试在适配器上调用notifyDataSetChanged()
mMyFragmentAdapter
,没有任何反应,ViewPager
中的片段继续使用创建时传递的相同数据。
编辑
在其他关于片段更新的问题中看到一些部分代码后,我也尝试过这个
public void update()
try
LineFragment fragment =
(LineFragment) getSupportFragmentManager().findFragmentByTag(
"android:switcher:"+R.id.view_pager+":0");
if(fragment != null)
if(fragment.getView() != null)
fragment.updateDisplay();
catch(RuntimeException e)
e.printStackTrace();
假设0是第一个Fragment-Tab片段的id(我不确定这种操作),但是fragment.updateDisplay();
没有被调用。
【问题讨论】:
你搜索的不多,不是吗? ***.com/questions/7379165/… @Luksprog mmm 这与我要求的有点不同。我需要了解 Fragment 如何获取 main 传递的数据,也许我遗漏了一些东西,但我真的不明白我该怎么做。如果我尝试为我的“LineFragment”创建自定义构造函数,则会收到错误消息“此片段应提供默认构造函数(没有参数的公共构造函数)” @AndreaF 检查对话框片段developer.android.com/reference/android/app/DialogFragment.html 使用静态static MyDialogFragment newInstance(int num)
传递参数,然后使用设置和获取参数。然后你传递像newInstance(value)
这样的值,如果这是你的意思,将数据从主传递到片段
@Raghunandan 谢谢,但 DialogFragment 是一个片段,它显示一个浮动在其活动窗口顶部的对话框窗口,这不是我的情况
@AndreaF 的概念是一样的,将其应用于片段
【参考方案1】:
在您的适配器中覆盖 getItemPosition
@Override
public int getItemPosition(Object object)
// POSITION_NONE makes it possible to reload the PagerAdapter
return POSITION_NONE;
之后
viewPager.getAdapter().notifyDataSetChanged()
应该可以。
【讨论】:
@Nino Handler.. 适配器中的 notifyDataSetChanged 是否刷新所有片段或唯一对用户可见的片段.. 所有当前附加的 - 如果你使用 FragmentStatePagerAdapter 这可能不是所有片段的情况 @RajaJawahar 这将更新当前片段【参考方案2】:我需要了解 Fragment 如何获取 main 传递的数据, 也许我错过了一些东西,但我真的不明白怎么可能 我这样做。
由此看来,您似乎想在创建Fragment
时传递数据。如果这是您想要的,则不应创建自定义构造函数(通常对于 Fragment
,您应该只有默认的无参数构造函数(因为平台需要它在某些时候重新创建 Fragment
))。
相反,您应该在 Bundle
中传递数据:
@Override
public Fragment getItem(int position)
switch (position)
//...
Bundle args = new Bundle();
args.put("a_string_representing_theKey", data)
LineFragment f = new LineFragment();
f.setArguments(args);
return f;
//...
这只有在数据可以放入Bundle
时才有效(参见Bundle
类的put...
方法,所有原语+ 对象为Parcelable
)。然后,您可以在片段中使用 getArguments()
检索参数。
您也可以让Fragment
直接从Activity
检索数据:
// in the lifecycle method where you want the data
((MainActivity)getActivity()).getDataForFragment(); // use the data
例如,我有这个显示图表的片段,(在我的意图中) 当我从 main,图表应该在 ViewPager 中更新
你似乎自相矛盾。为此,请使用我链接到的问题中的代码,当然只是调用您当前的 setFragment()
方法不会做任何事情,因为您只是更新两个变量的值,您需要让 UI 知道更改(比如调用另一种方法来重新创建视图层次结构,在图表视图上设置新值并调用invalidate()
等)。
编辑:
我链接到的问题中使用的代码应该可以工作,但您没有使用正确的代码。您有一个 FragmentStatePagerAdapter
,但您正在使用 FragmentPagerAdapter
的代码,这不起作用:
FragmentStatePagerAdapter a = (FragmentStatePagerAdapter) mViewPager.getAdapter();
LineFragment f = (LineFragment) a.instantiateItem(pager, thePositionYouWant);
请记住,上面的代码仅适用于可见片段加上每侧 1 个片段,其他片段将不可用(并且由于用户看不到它们或无法立即移动到它们它们不应该被更新)。
【讨论】:
感谢您的回答。简而言之,我需要根据 mainactivity 接收到的数据创建一个片段。 2-如果主要发生类似'setFragment(...)'的事情,每次都更改片段的数据。如果我可以使用 Bundle 执行此操作,您能否详细说明如何将其与 Fragment 一起使用? @AndreaF 我已经编辑了我的答案。您可以查看任何基本教程,了解如何使用Bundle
作为片段的参数。
@Raghunandan getItem()
方法来自FragmentPagerAdapter
/FragmentStatePagerAdapter
,他在其中创建了Fragment
,而您无法创建static
。
@Luksprog yup 现在明白了,我想我误解了这个问题。我认为它是一个片段。这里的getItem是FragmentPagerAdapter
的重写方法
@Luksprog 现在我已经了解如何将参数从主要活动传递到 Fragment,但不幸的是,如果我尝试更改数据并调用 notifyDataSetChanged()
没有任何反应【参考方案3】:
很简单的覆盖片段中的方法
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser)
actionView();
else
//no
【讨论】:
此方法已被弃用,有什么替代方法吗?【参考方案4】:如何以编程方式通过 Main Activity 在 View Pager 中更新刷新片段 经过长时间的努力,我找到了合适的解决方案
tablayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
@Override
public void onTabSelected(TabLayout.Tab tab)
refreshTab(tab.getPosition());// create a method
viewpager.setCurrentItem(tab.getPosition());
@Override
public void onTabUnselected(TabLayout.Tab tab)
@Override
public void onTabReselected(TabLayout.Tab tab)
);
private void refreshTab(int position)
switch (position)
case 0:
break;
case 1:
CompaniesInterest comP1 = (CompaniesInterest) viewpager.getAdapter().instantiateItem(viewpager, viewpager.getCurrentItem());
comP1.refreshpage();
break;
case 2:
TotalSelectedCompanies toTal = (TotalSelectedCompanies) viewpager.getAdapter().instantiateItem(viewpager, viewpager.getCurrentItem());
toTal.refreshpage();
// Create a interface for refresh data for fragmen
public interface Refreshpage
void refreshpage();
// implements Refreshpage interface in both fragment TotalSelectedCompanies and CompaniesInterest
//
@Override`enter code here`
public void refreshpage()
// do what you want to refresh
【讨论】:
以上是关于如何以编程方式通过 Main Activity 在 ViewPager 中更新刷新片段的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式设置的主题。如何重新加载 Activity 以应用