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



對於那些仍然面臨同樣的問題,我面對之前,當我有一個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個片段。 我認為一定有不對的地方,請糾正我,謝謝。

  1. 序列化數據必須加載到內存中。 這可以使用CursorLoader / AsyncTask / Thread來完成。 是否自動加載取決於您的代碼。 如果你使用的是CursorLoader ,它會自動加載,因為有一個註冊數據觀察者。

  2. 在調用viewpager.setAdapter(pageradapter) ,不斷調用適配器的getCount()來構建片段。 因此,如果數據被加載, getCount()可以返回0,因此不需要為顯示的數據創建虛擬片段。

  3. 加載數據後,由於getCount()仍為0,因此適配器不會自動構建片段,因此我們可以將實際加載的數據編號設置為由getCount()返回,然後調用適配器的notifyDataSetChanged()ViewPager開始通過內存中的數據創建片段(只是前兩個片段)。 它在返回notifyDataSetChanged()之前完成。 然後ViewPager擁有你需要的正確的片段。

  4. 如果數據庫和內存中的數據都更新(通過寫入),或者僅更新內存中的數據(寫回),或者只更新數據庫中的數據。 在最後兩種情況下,如果數據不是從數據庫自動加載到內存(如上所述)。 ViewPager和尋呼機適配器只處理內存中的數據。

  5. 所以當內存中的數據更新時,我們只需要調用適配器的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);
        }

    }
}

如果您有多個版本的相同片段,則可以使用相同的策略調用這些片段上的方法,以確定它是否是您希望更新的片段。





android-viewpager