如何得到ViewPager当前可见的碎片的实例: [英] How to get the instance of the currently visible fragment in ViewPager:

查看:103
本文介绍了如何得到ViewPager当前可见的碎片的实例:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要建,显示不同片段在 ViewPager 的应用程序。我添加这些片段与 ViewPager 是这样的:

I'm building an application that shows different fragments in a ViewPager. I add these fragments to the ViewPager like this:

 public void intialiseViewPager() 
 {
    List<Fragment> fragments = new Vector<Fragment>();
    numberOfTabs = application.currentReport.getODTabsList().size();
    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());
    mPagerAdapter  = new ViewPagerAdapter(getSupportFragmentManager(), fragments);
    mViewPager = (ViewPager)findViewById(R.id.pager);
    mViewPager.setAdapter(mPagerAdapter);
    mViewPager.setOffscreenPageLimit(0);
    mViewPager.setOnPageChangeListener(this);
}

正如你可以看到我传递给片段的字符串( tempTab.getTabId()),在这一行:

GridFragment gridFragment = GridFragment.newInstance(tempTab.getTabId());

在片段本身我这样做是为了初始化:

In the fragment itself I do this to initialize it:

public static final GridFragment newInstance(String tabId)
{
    GridFragment f = new GridFragment();
    Bundle bdl = new Bundle(2);
    bdl.putString(TAB_ID, tabId);
    f.setArguments(bdl);
    return f;
}

@Override
public void onCreate(Bundle savedInstanceState) 
{
    String tabId = getArguments().getString(TAB_ID);
    if (application.currentReport != null)
    {
        this.odTab = application.currentReport.getODTabByTabId(tabId);
    }
    else
    {
        startActivity(new Intent(getActivity(), LoginScrActivity.class));
    }
    super.onCreate(savedInstanceState);
}

这一切是为了不覆盖片段的默认空构造函数执行,因为我明白,这是不推荐的。

All this is performed in order to not override the default empty constructor of the fragment, as I understand that this is not recommended.

现在我需要获得 odTab 对象,我投入在这条线当前可见的碎片的实例:

Now I need to get the instance of the odTab object that I put into the currently visible fragment in this line:

this.odTab = application.currentReport.getODTabByTabId(tabId);

可能有人请向我解释如何可以这样做? 如何获取当前可见的片段实例,这样就可以拉odTab对象出来吗?

Could someone please explain to me how this could be done? How do I get the currently visible fragment instance so I can pull the odTab object out of it?

更新: 随着我在这里获得了建议,我添加了一个 odTab 对象实例调用的应用程序类 currentVisibleTab 和我中号设置odTab的情况是这样的:

UPDATE: With the suggestions I received here I have added an odTab object instance to the application class that is called currentVisibleTab and I'm setting the instance of the odTab like this:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) 
{
    Log.d(TAG, "setUserVisibleHint invoked!");
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) 
    {
        if (odTab != null && getActivity() != null)
        {
            Log.d(TAG, "Currently visable tab: "+odTab.getTabTitle());
            application.currentVisibleTab = odTab;
        }
    }   
}

UPDATE2: 这是我的 ViewPagerAdapter

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;
} 

public void removeAllFragments()
{
    this.fragments.clear();
}

public void addFragmentsListToAdapter(List<Fragment> fragments)
{
    this.fragments.addAll(fragments);
}

public List<Fragment> getFragments()
{
    return fragments;
}
}

在这我有一个列表所显示的 ViewPager 片段。这个列表是这样初始化的:

In it I have a List of fragments that are shown by the ViewPager. This list is initialized like this:

 List<Fragment> fragments = new Vector<Fragment>();

我不明白的是我如何获得一个参考目前片段引发从该列表的接口方式。 这是不是一个相关的问题,但也许你知道答案:<?code>列表之间的区别是什么和向量

What I don't understand is how I get a reference to the current fragment that triggered the interface method from this list. And this is not a related question but maybe you know the answer: What is the difference between List and Vector?

我还是选中此选项了。

推荐答案

我已经找到了当前可见片段的方法是使用 setUserVisibleHint 和接口背面的 ViewPager 。这种方法是在<一href="http://developer.android.com/reference/android/support/v4/app/Fragment.html#setUserVisibleHint%28boolean%29"相对=nofollow>片段类。覆盖它,并使用一个接口来调用回你的 ViewPager 。如果该片段是可见的 - 即返回true - 然后只使用一个参考的片段(无论是从列表中支持你的适配器或一个你作为一个实例变量存储),以获得任何你需要走出片段本身。我已经添加了code以下。

The way I've found the currently visible fragment is using setUserVisibleHint and an interface back to the ViewPager. This method is in the fragment class. Override it and use an interface to call back to your ViewPager. If the fragment is visible - i.e. it returns true - then just use a reference to your fragment (either from the list backing your adapter or one you stored as an instance variable) to get whatever you need out of the fragment itself. I've added the code below.

声明涉及到任何你想要做的接口。在我来说,我就是用这个来禁用 ViewPager 默认的X方向的监听器时,谷歌地图的实例是可见的,使得地图的滚动没有触发片段的变化

Declare an interface related to whatever you want to do. In my case I was using this to disable the ViewPager default x-direction listener when a Google Map instance was visible so that the scrolling of the map did not trigger the change of fragment.

public interface OnMapFragmentVisibleListener{
    public void mapVisible(boolean visible);
}

在片段:

@Override 
public void onAttach(Activity activity){ 
    super.onAttach(activity);
    try{
        mapFragmentVisibilityListener = (OnMapFragmentVisibleListener) activity;
        isAttached = true; //flag for whether this fragment is attached to pager
    } catch (ClassCastException e){
        throw new ClassCastException(activity.toString() + " must implement interface onAttach");
    }


@Override
public void setUserVisibleHint(boolean isVisibleToUser){
    if(isVisibleToUser && isAttached){ //if listener is called before fragment is attached will throw NPE
        mapFragmentVisibilityListener.mapVisible(true);
    }
}

有一件事情并不明显,直到我尝试这一点是增加了isAttached变量。我也重写片段onAttach方法,并设置为true,一旦它被调用。否则,会发生什么是你的片段将是可见的用户,并试图调用接口的 ViewPager ,在该接口初始化。

One thing that was not obvious until I tried this out was the addition of the isAttached variable. I also override the fragments onAttach method and set this to true once it is called. Otherwise what happens is your fragment will be visible to the user and try to call the interface to your ViewPager before the interface is initialized.

在我的 ViewPager 我只是实现了OnMapFragmentVisibleListener,然后添加所需的方法

In my ViewPager I just implement the OnMapFragmentVisibleListener and then add the required method

    @Override
public void mapVisible(boolean visible) {
    if(visible)
    viewPager.allowSwipe(false); //turn off viewPager intercept touch if map visible
}

在我来说,我用它来关闭 ViewPager 刷卡功能。不过,我可以很容易地打电话回我mapFragment的公共方法。我正好有3个片段在我的 ViewPager ,我保持一个参考。

In my case I used it to turn off the ViewPager swipe function. However, I could have easily called back to a public method in my mapFragment. I happen to have 3 fragments in my ViewPagerthat I keep a reference to.

更新

要找出当前显示的,你首先需要找出正在显示该片段的片段。可以做到这一点通过多种方式。最简单的是通过一些描述回到你的 ViewPager / FragmentActivity 与您之前创建的接口。

To find the fragment that is currently displayed, you first need to find out which fragment is being displayed. You can do this a number of ways. The easiest is to pass some descriptor back to your ViewPager / FragmentActivity with the interface you created before.

public interface OnFragmentVisibleListener{
    public void fragmentVisible(boolean true, String tag);
}

您的设置的问题是,您使用的是向量这实在是一个同步的列表存储您的片段引用。其结果是,没有通过它您可以在以后找到你的片段没有键值。片段具有由当它们被加入到活性片段的片段交易过程中创建的一个标记进行标识的能力。然而,在 ViewPager 设置,你不要单独添加的片段,因此在交易过程中不能添加标签。

The problem with your setup is that you're using a Vector which is really a synchronized List to store your fragment references. As a result, there is no key value by which you can locate your fragments later. Fragments have the ability to be identified by a tag that is created during the fragment transaction when they are added to the fragment activity. However, in a ViewPager setup, you do not add the fragments individually and so can't add tags during the transaction.

我的解决方案是回我的 BasePagerAdapter 的HashMap 我在其中存储由唯一的每个片段键。

My solution has been to back my BasePagerAdapter with a HashMap in which I store each fragment identified by a unique key.

 LinkedHashMap<String, Fragment> tabs = new LinkedHashMap<String, Fragment>();
 tabs.put("Frag1", fragment1);
 tabs.put("Frag2", fragment2);
 tabs.put("Frag3", fragment3);

然后,我用这个在适配器:

Then I use this in the adapter:

private class BasePagerAdapter extends FragmentPagerAdapter{

    private LinkedHashMap<String, Fragment> tabs;

    public BasePagerAdapter(LinkedHashMap<String, Fragment> tabMap, FragmentManager fm)
    {
        super(fm);
        this.tabs = tabMap;
    }

     // other basic methods

由于您的引用存储到键值,可以很容易地找到你想要的,因为你可以从的HashMap 键,返回键搜索片段。

Because your references are stored to key values, it's easy to find the fragment you're looking for because you can just search by key from the HashMap and return.

如果您不能更改设置,以摆脱向量你需要是(1)跟踪您的顺序在增加(假设片段是不是该片段动态地添加和删除),这样就可以通过索引获得,或(2)保持独立引用的每个片段。

If you cannot change the setup to get away from the Vector you need to either (1) keep track of which fragment you add in which order (assuming fragments are not added and removed dynamically) so that you can get it by index or (2) keep separate references to each fragment.

private Fragment x;

//in onCreate
x = new Fragment();

//in interface
if(tag.equals("x"){
    x.doSomething();
}

另一件事,使这更容易的是,我的片段都是子类。例如。每个执行不同的功能片段具有它自己的类。至于有每个类只有一个实例很容易找到,因为我没有任何重复。如果您使用的是片段类的所有通用成员,你只需要实现标签的一些系统,使得上述可能的途径之一。

Another thing that makes this easier is that my fragments are all sub-classed. E.g. each fragment that performs a different function has its own class. As there is only one instance of each class it is easy to find since I do not have any duplicates. If you're using all generic members of the Fragment class you just need to implement some system of tagging that makes one of the approaches above possible.

这篇关于如何得到ViewPager当前可见的碎片的实例:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆