android - viewpager教學 - viewpager tablayout
動態更新ViewPager? (12)
接受的答案是不明白的,這就是為什麼添加簡單的解決方案。 找到解決方案。
只需通知您的適配器 ,它的工作令人驚嘆,
參考代碼
void setAdapter(int position) {
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
// when notify then set manually current position.
viewPager.setCurrentItem(position);
pagerAdapter.notifyDataSetChanged();
}
在設置適配器並且想要刷新UI時調用此代碼。
在您的片段中添加此代碼進行刷新 使用instanceof
進行投射上下文。
((YourActivityName) getContext()).setAdapter(selectedTabPosition);
此代碼共享只是幫助尋找工作解決方案的目的,希望它有幫助!
我無法更新ViewPager中的內容。
一個問題:在FragmentPagerAdapter類中,方法instantiateItem()和getItem()的關係和正確用法是什麼?
我只使用getItem()來實例化並返回我的片段:
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
這運作良好(但據說我不能改變內容)。
所以我發現: ViewPager PagerAdapter沒有更新視圖
特別是關於方法instantiateItem()的討論:
“我的方法是對instantiateItem()方法中的任何實例化視圖使用setTag()方法”
所以現在我想要實現instantiateItem()。 但我不知道我必須返回那裡(返回是Object)以及與getItem(int position)的關係是什麼?
目前我使用getItem來實例化片段,這是錯誤的嗎? 但是,那麼我必須將片段放入實例變量中,還是不要實現getItem()......? 我只是不明白這一點。
我試著閱讀reference :
public abstract Fragment getItem(int position)
返回與指定位置關聯的碎片。
公共對象instantiateItem(ViewGroup容器,int位置)
創建給定位置的頁面。 適配器負責將視圖添加到此處給出的容器,儘管它只能確保在從finishUpdate(ViewGroup)返回時完成此操作。 參數
容器包含將在其中顯示頁面的視圖。 位置要實例化的頁面位置。
返回
返回表示新頁面的Object。 這不需要是一個視圖,但可以是頁面的其他容器。
......但我仍不明白他們是如何相關的以及我必須做什麼。
這是我的代碼。 我正在使用支持包v4。
ViewPagerTest
public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);
pager = (ViewPager)findViewById(R.id.slider);
String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};
adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);
((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}
private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();
//pager.setCurrentItem(0);
}
}
MyFragmentAdapter
class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;
public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}
@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}
@Override
public int getCount() {
return slideCount;
}
public void setData(String[] data) {
this.data = data;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
MyFragment
public final class MyFragment extends Fragment {
private String text;
public MyFragment(String text, Context context) {
this.text = text;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);
return view;
}
}
這裡也有人有類似的問題,沒有答案...
http://www.mail-archive.com/[email protected]/msg200477.html
在代碼中的notifyDataSetChanged()
之後,嘗試在ViewPager上使用notifyDataSetChanged()
。
如果您想使用FragmentStatePagerAdapter,請查看https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=37990 。 FragmentStatePagerAdapter存在問題,可能會或可能不會影響您的用例。
此外,鏈接也很少有解決方案..few可能適合您的要求。
對於那些仍然面臨同樣的問題,我面對之前,當我有一個ViewPager與7片段。 這些片段的默認值從api服務加載英文內容,但這裡的問題是我想從設置活動中更改語言,並且在完成設置活動後,我希望ViewPager在主要活動中刷新片段以匹配用戶的語言選擇並加載阿拉伯文內容,如果用戶在這裡選擇阿拉伯語,我第一次做什麼工作
1-您必須使用上面提到的FragmentStatePagerAdapter。
2 - 在mainActivity我重寫onResume並執行以下操作
if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}
3-i覆蓋了mPagerAdapter中的getItemPosition()並使其返回POSITION_NONE。
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
像魅力一樣工作
我使用EventBus庫來更新ViewPager
Fragment
內容。 邏輯很簡單,就像EventBus的文件怎麼做 。 無需控制FragmentPagerAdapter
實例。 代碼在這裡:
1:定義事件
定義哪些消息是需要更新的。
public class UpdateCountEvent {
public final int count;
public UpdateCountEvent(int count) {
this.count = count;
}
}
2.準備訂閱者
在下面的代碼中寫下需要更新的片段。
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
public void onEvent(UpdateCountEvent event) {//get update message
Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}
3.發生事件
在其他Activity
或其他需要更新參數的Fragment
編寫代碼
//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
我已經通過了上面的所有答案和其他一些帖子,但仍然找不到適合我的東西(使用不同的片段類型以及動態添加和刪除標籤)。 FWIW下面的方法是我的工作(以防其他人有相同的問題)。
public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
private static final String TAB1_TITLE = "Tab 1";
private static final String TAB2_TITLE = "Tab 2";
private static final String TAB3_TITLE = "Tab 3";
private ArrayList<String> titles = new ArrayList<>();
private Map<Fragment, Integer> fragmentPositions = new HashMap<>();
public MyFragmentStatePageAdapter(FragmentManager fm) {
super(fm);
}
public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
titles.clear();
if (showTab1) {
titles.add(TAB1_TITLE);
}
if (showTab2) {
titles.add(TAB2_TITLE);
}
if (showTab3) {
titles.add(TAB3_TITLE);
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return titles.size();
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
String tabName = titles.get(position);
if (tabName.equals(TAB1_TITLE)) {
fragment = Tab1Fragment.newInstance();
} else if (tabName.equals(TAB2_TITLE)) {
fragment = Tab2Fragment.newInstance();
} else if (tabName.equals(TAB3_TITLE)) {
fragment = Tab3Fragmen.newInstance();
}
((BaseFragment)fragment).setTitle(tabName);
fragmentPositions.put(fragment, position);
return fragment;
}
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
@Override
public int getItemPosition(Object item) {
BaseFragment fragment = (BaseFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);
Integer fragmentPosition = fragmentPositions.get(item);
if (fragmentPosition != null && position == fragmentPosition) {
return POSITION_UNCHANGED;
} else {
return POSITION_NONE;
}
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
fragmentPositions.remove(object);
}
}
我生活過同樣的問題,而且我搜查了太多次。 任何在或通過谷歌給出的答案不解決我的問題。 我的問題很簡單。 我有一個列表,我用viewpager顯示這個列表。 當我添加一個新元素到列表的頭部時,我刷新了viewpager nothings改變。 我的最終解決方案非常簡單,任何人都可以使用。 當一個新元素添加到列表並且想要刷新列表時。 首先將viewpager適配器設置為null,然後重新創建適配器並將其設置為viewpager。
myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);
確保您的適配器必須擴展FragmentStatePagerAdapter
我知道黨遲到了。 我已經通過調用TabLayout#setupWithViewPager(myViewPager);
解決了這個問題TabLayout#setupWithViewPager(myViewPager);
FragmentPagerAdapter#notifyDataSetChanged();
我遇到了這個問題並最終在今天解決了這個問題,所以我寫下了我所學到的內容,希望對於Android的ViewPager
和我的更新有所幫助。 我在API級別17中使用FragmentStatePagerAdapter
,目前只有2個片段。 我認為一定有不對的地方,請糾正我,謝謝。
序列化數據必須加載到內存中。 這可以使用
CursorLoader
/AsyncTask
/Thread
來完成。 是否自動加載取決於您的代碼。 如果你使用的是CursorLoader
,它會自動加載,因為有一個註冊數據觀察者。在調用
viewpager.setAdapter(pageradapter)
,不斷調用適配器的getCount()
來構建片段。 因此,如果數據被加載,getCount()
可以返回0,因此不需要為顯示的數據創建虛擬片段。加載數據後,由於
getCount()
仍為0,因此適配器不會自動構建片段,因此我們可以將實際加載的數據編號設置為由getCount()
返回,然後調用適配器的notifyDataSetChanged()
。ViewPager
開始通過內存中的數據創建片段(只是前兩個片段)。 它在返回notifyDataSetChanged()
之前完成。 然後ViewPager
擁有你需要的正確的片段。如果數據庫和內存中的數據都更新(通過寫入),或者僅更新內存中的數據(寫回),或者只更新數據庫中的數據。 在最後兩種情況下,如果數據不是從數據庫自動加載到內存(如上所述)。
ViewPager
和尋呼機適配器只處理內存中的數據。所以當內存中的數據更新時,我們只需要調用適配器的
notifyDataSetChanged()
。 由於片段已經被創建,適配器的onItemPosition()
將在notifyDataSetChanged()
返回之前被調用,在notifyDataSetChanged()
中不需要做任何事情,然後數據被更新。
由於某種原因,沒有任何答案適用於我,所以我不得不在我的fragmentStatePagerAdapter中調用super時重寫restoreState方法。 碼:
private class MyAdapter extends FragmentStatePagerAdapter {
// [Rest of implementation]
@Override
public void restoreState(Parcelable state, ClassLoader loader) {}
}
而不是從getItemPosition()
返回POSITION_NONE
並導致完整視圖重新創建,請執行以下操作:
//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
this.updateData = xyzData;
notifyDataSetChanged();
}
@Override
public int getItemPosition(Object object) {
if (object instanceof UpdateableFragment) {
((UpdateableFragment) object).update(updateData);
}
//don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}
你的片段應該實現UpdateableFragment
接口:
public class SomeFragment extends Fragment implements
UpdateableFragment{
@Override
public void update(UpdateData xyzData) {
// this method will be called for every fragment in viewpager
// so check if update is for this fragment
if(forMe(xyzData)) {
// do whatever you want to update your UI
}
}
}
和界面:
public interface UpdateableFragment {
public void update(UpdateData xyzData);
}
你的數據類:
public class UpdateData {
//whatever you want here
}
這個解決方案不適用於所有人,但在我的情況下,ViewPager中的每個片段都是不同的類,每次只有其中一個存在。
有了這個限制,這個解決方案是安全的,應該是安全的使用在生產中。
private void updateFragment(Item item) {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragments) {
if (fragment instanceof MyItemFragment && fragment.isVisible()) {
((MyItemFragment) fragment).update(item);
}
}
}
如果您有多個版本的相同片段,則可以使用相同的策略調用這些片段上的方法,以確定它是否是您希望更新的片段。