【问题标题】:ViewPager first two fragments are not in orderViewPager 前两个片段不按顺序
【发布时间】:2016-08-28 03:38:08
【问题描述】:

我正在制作一个使用 ViewPager 的应用程序,因此用户填写表单并保存进度,同时通过向右滚动继续到下一个片段。

还没有完成;但是我偶然发现了 Android 的一个奇怪行为。

我有大约 9 个片段,它会在调用 HomeActivity 时加载。第一个是SiteDetailsFragment,第二个是DevicePlacementDetailsFragment,以此类推。

我打算通过覆盖onPageSelected 来保存用户的当前进度,并利用片段位置来确定应该保存/验证哪一个。我调用了List<Fragment> fs = getSupportFragmentManager().getFragments(); 来存储片段的位置。

但是,当我测试应用程序时,它们两个似乎以相反的顺序实例化 - DevicePlacementDetailsFragmentfs 的第一个成员上,然后是 SiteDetailsFragmentDevicePlacementDetailsFragmentfs 的位置 0 上,而 SiteDetailsFragment 在位置 1 上,但在屏幕上它们的顺序正确。

当我向右滚动时,其余的片段会按顺序设置。

这让我很困惑,因为我必须确定片段的位置以及调用onPageSelected 时需要做什么。

下面是代码。我知道这很奇怪,但这是一项正在进行的工作。我还写了一段代码来解决这个问题。

import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.widget.Toast;

import com.xxx.psie_surveyandroid.R;
import com.xxx.psie_surveyandroid.adapters.ViewPagerAdapter;
import com.xxx.psie_surveyandroid.customlibs.CustomAppCompatActivity;
import com.xxx.psie_surveyandroid.fragments.CablingToIDUFragment_;
import com.xxx.psie_surveyandroid.fragments.CablingToTransmissionFragment_;
import com.xxx.psie_surveyandroid.fragments.DevicePlacementDetailFragment_;
import com.xxx.psie_surveyandroid.fragments.GroundFragment_;
import com.xxx.psie_surveyandroid.fragments.PhotoSiteSurveyFragment_;
import com.xxx.psie_surveyandroid.fragments.PowerDetailFragment_;
import com.xxx.psie_surveyandroid.fragments.RackAndRoomLayoutFragment_;
import com.xxx.psie_surveyandroid.fragments.SiteDetailFragment_;
import com.xxx.psie_surveyandroid.fragments.SpareFragment_;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;

import java.util.List;

/**
 * @author Cipleyo
 * @since 5/20/2016
 */
@EActivity(R.layout.home_activity_layout)
public class HomeActivity extends CustomAppCompatActivity {
    public final static String TAG = HomeActivity.class.getSimpleName();
    @ViewById Toolbar toolbar;
    @ViewById TabLayout tabLayout;
    @ViewById ViewPager vpForms;

    private int lastPos = 0;

    @AfterViews
    void init(){
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        setupViewPager(vpForms);
        tabLayout.setupWithViewPager(vpForms);

        vpForms.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                List<Fragment> fs = getSupportFragmentManager().getFragments();
                /*
                These strange lines of codes are for fixing the misplaced first two Fragments.
                Don't ask why - I have no idea.
                 */
                Fragment tempFragment = fs.get(0);
                if (!(tempFragment instanceof SiteDetailFragment_)) {
                    fs.set(0, fs.get(1));
                    fs.set(1, tempFragment);
                }
                /* End of strange lines of codes */
                Fragment f;
                f = fs.get(lastPos);
                if (lastPos > position) {   //left
                    Log.i(TAG, "Scrolled Left, f = " + f);
                } else {                    //right
                    Log.i(TAG, "Scrolled Right, f = " + f);
                }
                if (lastPos < position) {   //swipe right
                    if (f instanceof SiteDetailFragment_) {
                        if (!((SiteDetailFragment_) f).executeSave()) {
                            vpForms.setCurrentItem(lastPos);
                            Toast.makeText(getApplicationContext(), "Please complete the required fields!",
                                    Toast.LENGTH_SHORT).show();
                        } else
                            lastPos = position;
                    } else if (f instanceof DevicePlacementDetailFragment_){
                        if (!((DevicePlacementDetailFragment_) f).executeSave()){
                            vpForms.setCurrentItem(lastPos);
                            Toast.makeText(getApplicationContext(), "Please complete the required fields!",
                                    Toast.LENGTH_SHORT).show();
                        } else
                            lastPos = position;
                    } else if (f instanceof RackAndRoomLayoutFragment_){
                        if (!((RackAndRoomLayoutFragment_) f).executeSave()){
                            vpForms.setCurrentItem(lastPos);
                            Toast.makeText(getApplicationContext(), "Please complete the required fields!",
                                    Toast.LENGTH_SHORT).show();
                        } else
                            lastPos = position;
                    }
                } else
                    lastPos = position;
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    private void setupViewPager(ViewPager viewPager){
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new SiteDetailFragment_(), "Site Details");
        adapter.addFragment(new DevicePlacementDetailFragment_(), "Device Placement Detail");
        adapter.addFragment(new RackAndRoomLayoutFragment_(), "Rack And Room Layout");
        adapter.addFragment(new PhotoSiteSurveyFragment_(), "Photo Site Survey");
        adapter.addFragment(new PowerDetailFragment_(), "Power Details");
        adapter.addFragment(new GroundFragment_(), "Ground");
        adapter.addFragment(new CablingToTransmissionFragment_(), "Cabling To Transmission");
        adapter.addFragment(new CablingToIDUFragment_(), "Cabling To IDU");
        adapter.addFragment(new SpareFragment_(), "Spare");
        viewPager.setAdapter(adapter);
    }
}

我希望我能很好地描述我的问题。随时询问可能有帮助的任何其他信息。谢谢!

【问题讨论】:

标签: android


【解决方案1】:

根据getSupportFragmentManager().getFragments() deprecated?FragmentManager.getFragments() 隐藏在旧版本的 Android API 中。在最新版本的 API 中,它似乎已被完全删除。 (我在FragmentManagerSupportFragmentManager 的文档中看不到它。)你不应该使用这种方法。由于该方法未记录在案,因此其行为不可靠。

【讨论】:

  • 我明白了……我错过了,因为它没有给出折旧警告……我也看到了 cmets 部分提到的解决方法……我会试试的出去。感谢您指出。
  • @cipley 我认为它本身实际上并没有被“弃用”。它似乎从未打算作为一种公开可用的方法。
  • 感谢@Code-Apprentice 的提醒!我找到了更好的解决方法。已经测试过了,结果很好!我会立即发布答案
  • @cipley 随时在此处发布答案,以帮助将来可能遇到同样问题的任何人。
【解决方案2】:

我在这里找到了更好的解决方法: Is there a way to get references for all currently active fragments in an Activity?

正如@Code-Apprentice 指出的那样,getSupportFragmentAdapter().getFragments() 的行为不像我预期的那样。所以我使用Activity.onAttachFragment()采取了不同的路线

注意:我正在使用支持库的片段。如果你使用的是 Native Fragment,你应该重写 onAttachFragment 方法。

protected List<WeakReference<Fragment>> fragmentList = new ArrayList<>();

public void onAttachFragment(Fragment fragment){
    fragmentList.add(new WeakReference<>(fragment));
}

public List<Fragment> getActiveFragments(){
    ArrayList<Fragment> ret = new ArrayList<>();
    for (WeakReference<Fragment> ref : fragmentList){
        Fragment f = ref.get();
        if (f != null){
            if (f.isVisible()){
                ret.add(f);
            }
        }
    }
    return ret;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多