onPageSelected不适用于第一页

问题描述:

我的寻呼机适配器(扩展PagerAdepter)中有一个textview。我用MainActivity的onPageSelected更新这个textview。其位置> 0的更新文本视图,但起始页面(位置0)不会在启动时更新。当我向前滑动然后向后滑动;它设置位置0的值,但我不能将值设置为ON START。如何设置星级页面的值?onPageSelected不适用于第一页

public void onPageSelected(int position) { 

      switch (position) { 
       case 0: 

        PagerAdapter.tv.setText("value"); // => doesnt work on start 

        break; 

          default: 
            PagerAdapter.tv.setText("value"); 
             break; 
} 
} 

全码:

public class QuizStart extends SlidingFragmentActivity { 
@Override 
     protected void onCreate(final Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      this.setContentView(R.layout.activity_main); 

       mPager = (ViewPager)findViewById(R.id.pager);   
      QuestionPagerAdapter mAdapter = new QuestionPagerAdapter(); 

      mPager.setAdapter(mAdapter); 
      QuizStart.onPageSelected(0); 

     mPager.setOnPageChangeListener(new OnPageChangeListener() { 


      @Override 
      public void onPageScrollStateChanged(int arg0) { } 

      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) { } 

      @Override 
      public void onPageSelected(int position) { 

      switch (position) { 
       case 0: 

        PagerAdapter.tv.setText("value"); // => doesnt work on start 

        break; 

          default: 
            PagerAdapter.tv.setText("value"); 
             break; 
       } 
      } 

     }); 
} 
} 
+0

为什么你PageAdapter有它的风景吗?这听起来很腥。你想达到什么目的? – dmon 2013-04-18 03:52:50

+0

我从数据库中获取数据并将其设置为paderadapters textview – metemet06 2013-04-18 03:58:35

您可以手动调用onPageSelected(0)当您创建OnPageChangeListener设置开始状态:

OnPageChangeListener pageChangeListener = new OnPageChangeListener() { 
    @Override 
    public void onPageScrollStateChanged(int arg0) { } 

    @Override 
    public void onPageScrolled(int arg0, float arg1, int arg2) { } 

    @Override 
    public void onPageSelected(int position) { 

     switch (position) { 
     case 0: 
      QuizStart.next.setText(getmycurrentpage()+""); 
      break; 

     default: 

      QuizStart.next.setText(getmycurrentpage()+""); 
      break; 
     } 
    } 
}); 

    mPager.setOnPageChangeListener(pageChangeListener); 
    // do this in a runnable to make sure the viewPager's views are already instantiated before triggering the onPageSelected call 
    mPager.post(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      pageChangeListener .onPageSelected(viewPager.getCurrentItem()); 
     } 
    }); 

编辑

现在它将会不克等Null Pointer exception通过如指出@ metemet06

+0

我该如何使用它?我找不到 – metemet06 2013-04-18 04:17:43

+0

紧跟在你的'viewPager.setAdapter(pagerAdapter)'后面,调用'pagerAdapter.onPageSelected(0)' – ianhanniballake 2013-04-18 04:43:17

+0

那么我会在pagerAdapter中创建onPageSelected()方法吗? – metemet06 2013-04-18 04:47:20

在我看来,你真的想要做什么是压倒一切的getPageTitle(),然后在其他地方,抓住该网页标题并将其设置为一个TextView的文本。

通过这种方式初始化您的活动,初始化PagerAdapter并致电getTitle(0)。这会让你获得页面0的标题。现在在活动的textview中设置它。稍后,只要您更改页面,只需拨打getTitle(newPosition)并更新该TextView即可。

您可能使用一些AsyncTasks来加载数据集,并且很难确定哪个任务是最后一个任务完成的。只有在完成最后一项任务后,当整个数据集完成时,您才可以调用OnPageSelected,因为它在整个数据集上对UI执行刷新。

而不是在第一次加载页面时手动调用OnPageSelected函数,而是逐步建立“正常”UI。稍后,当用户更改页面时,数据集应该是完整的,并且保存在OnPageSelected函数中进行更新。

因为我做了什么,在这里建议,并没有工作,我将发布什么做的工作对我来说是将实体化功能onPageScrolled,像这样:

@Override 
    public void onPageScrolled(int arg0, float arg1, int arg2) { 

      adapter.closeText(arg0, viewPager); 

    } 

也许它的工作的原因是onPagesScrolled会在android任务管理器的下方被激活,所以我们可以防止页面被夸大的不需要的情况,并跳过视图的侦听器附件。

我通过在我的活动的onCreate()方法中添加应为第一页执行的代码来修复了我的应用程序中的问题。

它不是最漂亮的黑客,并涉及一些冗余的代码,但因为我只想在页面更改时加载一些文本数据,所以对我来说这是最简单的方法。

调用onPageSelected()手动导致NullPointerExceptions,只是das在上面的其他注释中描述。

我的解决方案是扩展寻呼机适配器,并在其中创建一个接口。然后让适配器在创建适配器后只调用一次接口。在界面回调里,你可以调用onPageChanged方法而不会有nullpointerexception。将此类添加到您的项目并从中扩展您的适配器。在将适配器设置为viewpager之前,不要忘记将监听器设置为适配器。适配器类如下:

public abstract class ExtendedPagerAdapter extends FragmentPagerAdapter { 

private boolean instantiated; 
private AdapterListener adapterListener; 

public interface AdapterListener { 
    void onAdapterInstantiated(); 
} 

public ExtendedPagerAdapter(FragmentManager fragmentManager) { 
    this(fragmentManager, null); 
} 

public ExtendedPagerAdapter(FragmentManager fragmentManager, AdapterListener adapterListener) { 
    super(fragmentManager); 
    this.adapterListener = adapterListener; 
    instantiated = false; 
} 

@Override 
public void finishUpdate(ViewGroup container) { 
    super.finishUpdate(container); 
    if (!instantiated) { 
     instantiated = true; 
     if (adapterListener != null) { 
      adapterListener.onAdapterInstantiated(); 
     } 
    } 
} 

public void setAdapterInstantiatedListener(AdapterListener adapterListener) { 
    this.adapterListener = adapterListener; 
} 
} 
+0

这是一个不错的主意,在我的情况下完美!我想花更多的时间来研究在片段连接到活动之后是否实际调用了finishUpdate。 – Entreco 2016-05-25 07:30:04

+0

谢谢:)根据谷歌[FragmentPagerAdapter.finishUpdate](https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html#finishUpdate(android.view.ViewGroup))被称为当所示页面的更改已完成。所以,每当片段发生变化时,都会调用完成更新。此外,如果我们深入了解源代码,我们可以看到这种方法提交并执行所有未完成的交易:) – 2016-05-25 07:39:45

+0

它值得更多upvotes – deviant 2017-10-06 15:52:15

此代码适用于我。首先初始化pagechange侦听器。 setCurrentItem之后。

viewPager.setAdapter(adapter); 
     viewPager.setOffscreenPageLimit(1); 

     final ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
     } 

     @Override 
     public void onPageSelected(int position) { 

     } 

     @Override 
     public void onPageScrollStateChanged(int state) { 
     } 
     }; 
     viewPager.addOnPageChangeListener(listener); 
     viewPager.setCurrentItem(position); 

工作对我来说下一个代码

viewPager.addOnPageChangeListener(myOnPageChangeListener); 

ViewPager.OnPageChangeListener myOnPageChangeListener = new ViewPager.OnPageChangeListener() { 

    //declare key 
    Boolean first = true; 

    @Override 
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
     if (first && positionOffset == 0 && positionOffsetPixels == 0){ 
      onPageSelected(0); 
      first = false; 
     } 
    } 

    @Override 
    public void onPageSelected(int position) { 
     //do what need 
    } 

    @Override 
    public void onPageScrollStateChanged(int state) { 
    } 
}; 
+0

这是一个很好的技巧,可以轻松解决问题。 – GregM 2017-03-02 16:02:39

其实我找到了一个很好的方法基于这个answer

问题是当设置侦听器时ViewPager未完全加载,第一个页面被调用,但ViewPager中的片段尚未完全初始化。

为了解决这个问题我只是保持一个变量知道,如果第一页被称为与否:

private boolean mFirstPageCalled = false; 
听者

然后:

@Override 
public void onPageSelected(int position) { 

    if(mFirstPageCalled) { 
     // Do your thing 
    } else { 
     mFirstPageCalled = true; 
    } 
} 

的最后一件事要做是处理已被遗漏的第一页,这可以在ViewPager完全创建时完成:

mViewPager.post(new Runnable(){ 
     @Override 
     public void run() { 
      // Do your thing 
     } 
    }); 

在我来说,我只是叫回来这里的当前片段显示,并在其上工作:

Fragment currentFragment = mPagerAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem()); 
currentFragment.customAction(); 

post方法只调用一次,如此完美处理的第一页的情况。

我的解决办法是延长ViewPager

class MyViewPager extends ViewPager { 

    private List<OnPageChangeListener> _Listeners = new ArrayList<>(); 

    public MyViewPager(Context context) { 
     super(context); 
    } 

    public MyViewPager(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    public void addOnPageChangeListener(OnPageChangeListener listener) { 
     super.addOnPageChangeListener(listener); 
     _Listeners.add(listener); 
    } 

    @Override 
    public void removeOnPageChangeListener(OnPageChangeListener listener) { 
     super.removeOnPageChangeListener(listener); 
     _Listeners.remove(listener); 
    } 

    @Override 
    public void setCurrentItem(final int item) { 
     if (item != getCurrentItem()) { 
      super.setCurrentItem(item); 
     } else { 
      post(new Runnable() { 
       @Override 
       public void run() { 
        dispatchOnPageSelected(item); 
       } 
      }); 
     } 
    } 

    private void dispatchOnPageSelected(int position) { 
     for (int i = 0, size = _Listeners.size(); i < size; i++) { 
      OnPageChangeListener listener = _Listeners.get(i); 
      if (listener != null) { 
       listener.onPageSelected(position); 
      } 
     } 
    } 
}