3

私は正常に機能するものを持っていますFragmentPagerAdapterが、私が疑問に思っているのFragmentPagerAdapterは、が最後のビューにある場合、どうすれば最初のビューにループバックして通常のように続行できるかということです

これは私が使用している私のサンプルコードです

public class FragmentPager extends FragmentActivity {
MyAdapter mAdapter;
ViewPager mPager;
static final int NUM_ITEMS = 5;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mAdapter = new MyAdapter(getSupportFragmentManager());

    mPager = (ViewPager)findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);
}

public static class MyAdapter extends FragmentPagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(position);
    }
}

public static class MyFragment extends ListFragment{
    int mNum;

    /**
     * Create a new instance of CountingFragment, providing "num"
     * as an argument.
     */
    static MyFragment newInstance(int num) {
        MyFragment f = new MyFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

    /**
     * When creating, retrieve this instance's number from its arguments.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mNum = getArguments() != null ? getArguments().getInt("num") : 1;
    }

    /**
     * The Fragment's UI is just a simple text view showing its
     * instance number.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_pager_list, container, false);
        View tv = v.findViewById(R.id.text);
        ((TextView)tv).setText("Fragment #" + mNum);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, new String[] {"test1","test2","test3","test4","Test5"}));
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Log.i("FragmentList", "Item clicked: " + id);
    }
}

}

基本的に、最後に到達したときに、他のフラグメントと同じように最初のフラグメントを表示するにはどうすればよいですか?

すなわち。A->B、、 および 後方 、、B->C_ C->AA->CC->BB->A

4

3 に答える 3

3

これが私の解決策です。画面の数は「n」(この場合は5)です。リストの最後にある最初の画面に戻りたいので、最後の画面の正確なコピーである「別の画面を追加」します。スクリーンし、逆方向にもこれを行います。基本的に、「n」画面が+2(この場合は7)になりました。画面はこのように設定さcopy of Cれ、、、、次にA、特定のページでのスワイプを監視するようにジェスチャーリスナーを設定します。BCcopy of A

リストの最後(「Aのコピー」)で左へのスワイプを検出した場合は、> a certain number of pixelsページに移動しA、通常のページ回転でスワイプし続けます。

反対方向にスワイプする場合も同様です。

問題

ViewPager現在表示しているページの前後にページをロードするため、ループをシミュレートするために終了ページの1つから移動すると少し遅くなりますが、ページリストの最後または最初にいるため、技術的には次のページがないため、通常のように次のページ。これは実際には、リスト行ごとに複雑なカスタムビューがある場合にのみ発生します

これは、シームレスに見えず、コピーされたページから実際のページ、つまりAからAのコピーに移動するときにアニメーション化されるため、ページスクロールのアニメーションでは使用できません。

また、それは時々ページの終わりで立ち往生しているように見えます、そして私は理由がわかりません

これは、Android開発者サイトのviewpagerの例に基づいた私の完全なデモアプリケーションです

public class FragmentPager extends FragmentActivity{
MyAdapter mAdapter;
public static ViewPager mPager;
static int currentPage = 1;
static final int NUM_ITEMS = 7;
public static View vContainer;
float dxInitial=0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mAdapter = new MyAdapter(getSupportFragmentManager());

    mPager = (ViewPager)findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);
    mPager.setCurrentItem(1,false);

    mPager.setOnTouchListener(new OnTouchListener(){

        @Override
        public boolean onTouch(View v, MotionEvent event) {


            if(event.getAction() == MotionEvent.ACTION_DOWN){
                dxInitial=event.getX();
                Log.d("INITIAL X", String.valueOf(dxInitial));
            }else if(event.getAction() == MotionEvent.ACTION_MOVE){
                if(event.getX() - dxInitial > 100 && currentPage==1){
                    mPager.setCurrentItem(6,false);
                }else if(dxInitial - event.getX() > 100 && currentPage==5){
                    mPager.setCurrentItem(0,false);
                }else if(dxInitial - event.getX() > 50 && currentPage==6){
                    mPager.setCurrentItem(1,false);
                }else if(event.getX() - dxInitial > 50 && currentPage==0){
                    mPager.setCurrentItem(5,false);
                }
            }

            /*if(Math.abs(dx) > Math.abs(dy)) {
                if(dx>75){ directiion = "right";
                }else if{
                    direction = "left";
                }
            } else {
                if(dy>0) direction = "down";
                else direction = "up";
            }*/

            return false;
        }

    });
    mPager.setOnPageChangeListener(new OnPageChangeListener(){

        @Override
        public void onPageScrollStateChanged(int state) {
            // TODO Auto-generated method stub
            if(state == ViewPager.SCROLL_STATE_IDLE){

            }
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int arg0) {
            currentPage=arg0;

        }

    });
}

public static class MyAdapter extends FragmentPagerAdapter{
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(position);
    }

    @Override
    public Object instantiateItem(View container, int position) {
        vContainer=container;
        return super.instantiateItem(container, position);

    }
}

public static class MyFragment extends ListFragment{
    int mNum;

    /**
     * Create a new instance of CountingFragment, providing "num"
     * as an argument.
     */
    static MyFragment newInstance(int num) {
        MyFragment f = new MyFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

    /**
     * When creating, retrieve this instance's number from its arguments.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mNum = getArguments() != null ? getArguments().getInt("num") : 1;
    }

    /**
     * The Fragment's UI is just a simple text view showing its
     * instance number.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_pager_list, container, false);
        View tv = v.findViewById(R.id.text);
        if(mNum == 6){
            mNum=1;
        }else if(mNum==7){
            mNum=5;
        }else if(mNum==0){
            mNum=5;
        }
        ((TextView)tv).setText("Fragment #" + mNum);
        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, new String[] {"test1","test2","test3","test4","Test5"}));
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        Log.i("FragmentList", "Item clicked: " + id);
    }
}

}
于 2012-11-02T23:17:31.117 に答える
1

これはかなりのハックですが、私にとっては非常にうまく機能します。

@Override
public int getCount() {
    return NUM_ITEMS * 1000;
}

これにより、ページが1000x「ループ」します。getItemで%操作を使用することを忘れないでください。

@Override
public Fragment getItem(int position) {
    position = position % 1000;
    return MyFragment.newInstance(position);
}
于 2012-10-08T17:01:09.610 に答える
0

tyczjの回答に基づいてKotlinソリューションを作成しました。これは、アダプターの作成後にカルーセルアイテムが読み込まれるタイミング(サーバーからのアイテムの読み込みなど)を処理し、タッチリスナーを取得せず、アイドル状態を待機します。 ViewPager2。私の場合、ユーザープロファイルのカルーセルがありました。

tycjzの回答によると、アイテムのセットがある場合A B C D、ViewPager2は機能的にはとして終了しますC A B C D Aが、ViewPager2 @位置1を0ではなく開始するため、で終了しAます。

inner class UserProfileSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {

    var profileToJumpTo: Int? = null

    override fun getItemCount(): Int {
        if (userIdsForLocalUsers.size > 0) {
            return userIdsForLocalUsers.size + 2
        }
        return userIdsForLocalUsers.size
    }

    override fun createFragment(position: Int): Fragment {
        var positionToUse = position - 1
        if (position > userIdsForLocalUsers.size)
        {
            positionToUse = 0
        }
        if (positionToUse < 0)
        {
            positionToUse = userIdsForLocalUsers.size - 1
        }
        val userId = userIdsForLocalUsers[positionToUse]
        this@ProfileViewModel.availableUserProfilesHash[userId].let {userProfile ->
            return CarouselUserProfileFragment.newInstance(userProfile!!)
        }
    }
}

以下のようにPageAdapterの「offby1」のポジショニングの問題を管理した後、ViewPager2onPageSelectedイベントが発生したときにループの開始時と終了時のどちらにいるかを判断し、ページが表示されたときにジャンプするページを選択できます。のアイドル状態onPageScrollStateChanged。したがってFragment、ViewPager2が存在する場所では次のようになります。

this.profiles_view_pager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() {
    override fun onPageScrollStateChanged(state: Int) {
        if (state == ViewPager2.SCROLL_STATE_IDLE) {
            val adapter = this@CarouselFragment.profiles_view_pager.adapter as ProfileViewModel.UserProfileSlidePagerAdapter
            val profileToJumpTo = adapter.profileToJumpTo
            profileToJumpTo?.let {
                this@CarouselFragment.profiles_view_pager.setCurrentItem(profileToJumpTo, false)
                adapter.profileToJumpTo = null
            }
        }
        super.onPageScrollStateChanged(state)
    }
    override fun onPageSelected(position: Int) {
        val adapter = this@CarouselFragment.profiles_view_pager.adapter as ProfileViewModel.UserProfileSlidePagerAdapter
        adapter.itemCount.let { itemCount ->
            if (position == 0) {
                adapter.profileToJumpTo = itemCount - 2
            }
            if (position == itemCount - 1) {
                adapter.profileToJumpTo = 1
            }
        }
        super.onPageSelected(position)
    }
})

また、現在のアイテムを「+1」に設定するために監視するLiveDataもありました。

this.profileViewModel.loadUserProfilesResult.observe(viewLifecycleOwner, Observer {     
    this.profiles_view_pager.setCurrentItem(1, false)
 })
于 2020-06-17T19:31:44.467 に答える