Fragments和FragmentPagerStateAdapter - 重新创建具有相同id的视图失败

时间:2013-12-10 15:18:03

标签: android fragment fragmentpageradapter

我正在使用ViewPager FragmentPagerStateAdapter。每个页面都有一个列表,手动管理=>我通过从xml中扩展布局来为这些行创建视图。结果是,不同行中的视图具有相同的id。因为行是从XML膨胀的......

现在的行为如下:

第1页如下:

// Page 1:
// Row 1: EditText = "Test1" 
// Row 2: EditText = "Test2"

我滑到第2页然后再到第3页,之后我再次滑回第1页,第1页看起来如下:

// Page 1:
// Row 1: EditText = "Test2" 
// Row 2: EditText = "Test2"

问题:所有EditTexts都显示列表中lastEditText的值...(注意,EditTexts具有相同的ID)。

如果我手动将EditTexts的id设置为行索引,一切正常。

这是正常的吗?这个问题有一个简单(好)的解决方案吗?

1 个答案:

答案 0 :(得分:1)

Tt似乎是Android 3.X中的一个错误

解决方案是手动设置ID,因此当Fragment变为不可见时,它们永远不会在片段之间匹配或重置id。 我喜欢第二个,因为它可以很容易地被禁用或启用,并且不需要特殊的ID处理。

/**
 * Used for resetting and restoring View id's. This is used as a workaround for
 * Android 3.x when ViewPager Fragment instances with the same layout have
 * problems referencing next focus id's.
 */
public final class ViewIdResetter {

    private final Map<View, Integer> viewMap;

    public ViewIdResetter(final View rootView) {
        this.viewMap = new HashMap<View, Integer>();
        this.fillmap(rootView);
    }

    private void fillmap(final View view) {
        if (view instanceof ViewGroup) {
            final ViewGroup vg = (ViewGroup) view;
            for (int i = 0; i < vg.getChildCount(); i++) {
                this.fillmap(vg.getChildAt(i));
            }
        }
        this.viewMap.put(view, view.getId());
    }

    public void clearIds() {
        for (final View key : this.viewMap.keySet()) {
            key.setId(-1);
        }
    }

    public void restoreIds() {
        for (final View key : this.viewMap.keySet()) {
            key.setId(this.viewMap.get(key));
        }
    }

}

碎片

private ViewIdResetter resetter;

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    this.resetter = new ViewIdResetter(view);
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        if (this.resetter != null) {
            this.resetter.restoreIds();
        }
    } else {
        if (this.resetter != null) {
            this.resetter.clearIds();
        }
    }
}

当片段变为可见时,ViewPager会触发setUserVisibleHint。 ViewIdResetter确保一次只有一个Fragment具有相同的id。