2013-04-18 13 views
42

Trình điều khiển máy nhắn tin của tôi (mở rộng PagerAdepter) có chế độ xem văn bản trong đó. Và tôi cập nhật textview này với onPageSelected của MainActivity. Văn bản cập nhật của nó cho vị trí> 0, nhưng trang bắt đầu (vị trí 0) không cập nhật khi khởi động. Khi tôi vuốt về phía trước rồi vuốt lại; nó đặt giá trị cho vị trí 0 NHƯNG tôi không thể đặt giá trị ON BẮT ĐẦU. Làm cách nào để đặt giá trị cho trang sao?onPageSelected không hoạt động đối với trang đầu tiên

public void onPageSelected(int position) { 

      switch (position) { 
       case 0: 

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

        break; 

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

Full Code:

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

Tại sao PageAdapter của bạn có một Xem trong nó? Điều đó nghe có vẻ khó khăn để bắt đầu. Bạn đang cố gắng để thực hiện? – dmon

+0

Tôi nhận dữ liệu từ cơ sở dữ liệu và đặt dữ liệu đó thành chế độ xem văn bản của chương trình – metemet06

Trả lời

49

Bạn có thể tự gọi onPageSelected(0) khi bạn tạo OnPageChangeListener của bạn để thiết lập trạng thái bắt đầu:

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

Sửa

Bây giờ nó sẽ không g et Null Pointer exception như chỉ bởi @ metemet06

+0

Tôi có thể sử dụng nó như thế nào? Tôi không thể tìm ra – metemet06

+0

Ngay sau 'viewPager.setAdapter (pagerAdapter)' của bạn, hãy gọi 'pagerAdapter.onPageSelected (0)' – ianhanniballake

+0

Vì vậy, tôi sẽ tạo phương thức onPageSelected() trong pagerAdapter? – metemet06

0

Dường như với tôi rằng những gì bạn thực sự muốn làm là trọng getPageTitle(), và sau đó, ở một nơi khác, grabbing rằng tiêu đề trang và đặt nó dưới dạng văn bản của TextView.

Bằng cách đó, khi bạn khởi tạo hoạt động của mình, hãy khởi tạo PagerAdapter và gọi getTitle(0). Điều này sẽ giúp bạn có được tiêu đề cho trang 0. Bây giờ hãy đặt tiêu đề đó trong chế độ xem văn bản của Hoạt động. Sau đó, bất cứ khi nào bạn thay đổi các trang chỉ cần gọi getTitle(newPosition) và cập nhật TextView đó.

0

Bạn có thể sử dụng một số AsyncTask để tải tập dữ liệu và khó xác định tác vụ nào sẽ là tác vụ cuối cùng để hoàn thành. Và chỉ sau nhiệm vụ cuối cùng đó, khi toàn bộ tập dữ liệu hoàn tất, bạn có thể gọi OnPageSelected, vì nó đang thực hiện lệnh xả trên giao diện người dùng trên toàn bộ tập dữ liệu.

Thay vì gọi hàm OnPageSelected theo cách thủ công khi trang được tải lần đầu tiên, thay vì xây dựng bước UI theo bước "bình thường". Sau đó, khi người dùng thay đổi trang, tập dữ liệu phải hoàn thành và nó được lưu để cho phép cập nhật được thực hiện trong chức năng OnPageSelected.

0

Bởi vì tôi đã làm những gì đã được đề xuất ở đây và nó đã không làm việc, tôi sẽ đăng những gì đã làm công việc đối với tôi là thêm chức năng tạo đối tượng để onPageScrolled, như vậy:

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

      adapter.closeText(arg0, viewPager); 

    } 

Có lẽ lý do nó làm việc là onPagesScrolled được kích hoạt xa hơn dòng của trình quản lý tác vụ android, vì vậy chúng tôi ngăn chặn tình huống không mong muốn khi trang được tăng cao bằng cách bỏ qua phần đính kèm của người nghe vào chế độ xem.

1

Tôi đã khắc phục sự cố trong ứng dụng của mình bằng cách thêm mã sẽ được thực hiện cho trang đầu tiên trong phương thức onCreate() của hoạt động của tôi.

Nó không phải là hack đẹp nhất và liên quan đến một số mã dự phòng, nhưng vì tôi chỉ muốn tải một số dữ liệu văn bản khi các trang đang thay đổi nó là cách dễ nhất để làm điều đó trong trường hợp của tôi.

Gọi onPageSelected() theo cách thủ công gây ra NullPointerExceptions, chỉ cần được mô tả trong các nhận xét khác ở trên.

3

Giải pháp của tôi là mở rộng bộ điều hợp máy nhắn tin và tạo một giao diện bên trong nó. Sau đó, làm cho bộ điều hợp chỉ gọi giao diện một lần sau khi tạo bộ điều hợp. Bên trong giao diện gọi lại, bạn có thể gọi phương thức onPageChanged mà không có nullpointerexception.Thêm lớp này vào dự án của bạn và mở rộng bộ điều hợp từ nó. Đừng quên đặt trình lắng nghe thành bộ điều hợp trước khi đặt bộ điều hợp cho chế độ xem. Lớp bộ điều hợp bên dưới:

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

Đây là một ý tưởng hay và trong trường hợp của tôi hoạt động hoàn hảo! Tôi muốn dành nhiều thời gian hơn để điều tra liệu 'finishUpdate' có thực sự được gọi sau khi đoạn đã được đính kèm vào hoạt động hay không. – Entreco

+0

Cảm ơn :) Theo Google [FragmentPagerAdapter.finishUpdate] (https://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html#finishUpdate (android.view.ViewGroup)) được gọi khi thay đổi trong các trang được hiển thị đã được hoàn thành. Vì vậy, mỗi đoạn thời gian đã thay đổi, kết thúc cập nhật được gọi. Ngoài ra nếu chúng ta đi sâu vào nguồn, chúng ta có thể thấy rằng phương thức này cam kết và thực hiện tất cả các giao dịch đang chờ xử lý :) –

+0

nó xứng đáng được nhiều hơn upvotes – deviant

0

Mã này làm việc cho tôi. Đầu tiên khởi tạo trình lắng nghe pagechange. Sau khi 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); 
25

Đối với tôi việc mã tiếp theo

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

Đây là một mẹo tốt để giải quyết vấn đề một cách dễ dàng. – GregM

0

Thực ra tôi đã tìm được cách tốt dựa trên số answer này.

Vấn đề là ViewPager không được tải đầy đủ khi người nghe được thiết lập, trang đầu tiên được gọi nhưng các mảnh bên trong ViewPager chưa được khởi tạo đầy đủ.

Để khắc phục điều đó tôi chỉ cần giữ một biến để biết nếu trang đầu tiên đã được gọi là hay không:

private boolean mFirstPageCalled = false; 

Sau đó, trong người nghe:

@Override 
public void onPageSelected(int position) { 

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

Điều cuối cùng để làm là để xử lý trang đầu tiên đã bị bỏ qua, điều này có thể được thực hiện sau khi ViewPager đã được tạo hoàn toàn với:

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

Trong trường hợp của tôi, tôi chỉ cần gọi trở lại đây đoạn hiện nay cho thấy và làm việc trên nó:

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

Phương pháp post chỉ được gọi một lần, quá hoàn hảo để xử lý các trường hợp trang đầu tiên.

0

Giải pháp của tôi là một mở rộng 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); 
      } 
     } 
    } 
}