【问题标题】:instantiateItem(ViewGroup, int) in PagerAdapter and AddView in ViewPager confusionPagerAdapter 中的 instantiateItem(ViewGroup, int) 和 ViewPager 中的 AddView 混淆
【发布时间】:2011-09-01 23:48:11
【问题描述】:

到目前为止,我一直在整理示例以了解整个 Android SDK 的 API。然而,我陷入了僵局。

我正在尝试使用 XML 文件中的 2 个 TextView 为 LinearLayout 充气。这些将是被分页的视图。我根本无法让它工作,并意识到我完全不明白代码发生了什么。

查看源代码,我可以看到 ViewPager.addNewItem 方法从提供的适配器调用 InstantiateItem。并且 addNewItem 在populate() 中被调用。 populate() 在许多其他地方被调用。

无论如何,在示例中,我已经体验到,当为 PagerAdapter 重写该方法时,必须在从 ViewPager 作为参数传递的 ViewPager 集合上包含对 addView() 的调用。

如果我希望添加多个视图,我认为这将是多次调用 addView() 的情况,但由于 instantiateItem() 将 Object 返回给 ViewPager(在示例中我让它返回它添加的视图)我不知道返回什么。我试过返回膨胀的视图和其他一些东西。

请问,有人能解释一下这里发生了什么吗?

非常感谢。

@Override
public Object instantiateItem(View collection, int position) {

    layout = inflater.inflate(R.layout.animallayout, null);
    TextView tv = (TextView) layout.findViewById(R.id.textView1);
    tv.setText("1________________>" + position);

    TextView tv2 = (TextView) layout.findViewById(R.id.textView2);
    tv.setText("2________________>" + position);

    ((ViewPager) collection).addView(layout);
    return layout;
}

【问题讨论】:

标签: android layout android-viewpager


【解决方案1】:

我最近实现了这一点,这是我的 instantiateItem 方法(为了便于阅读,它有点小。

@Override
public Object instantiateItem(View collection, int position) {
    Evaluation evaluation = evaluations.get(position);

    View layout = inflater.inflate(R.layout.layout_evaluation, null);

    TextView evaluationSummary = (TextView) layout.findViewById(R.id.evaluation_summary);
    evaluationSummary.setText(evaluation.getEvaluationSummary());

    ((ViewPager) collection).addView(layout);

    return layout;
}

@Override
public void destroyItem(View collection, int position, Object view) {
     ((ViewPager) collection).removeView((View) view);
}

@Override
public boolean isViewFromObject(View view, Object object) {
    return view == object;
}

所以对于显示的页面,我使用位置作为索引从我的evaluations 列表中获取数据。 然后膨胀Layout,它有我也将添加我的数据的视图。 然后我得到TextView 来设置评估摘要文本。 然后将整个Layout 添加到ViewPager。 最后Layout 也被返回。

如果您仍然无法获得它,请发布您的代码。

【讨论】:

  • 感谢 C0de 攻击。我可以看到您正在夸大布局。这里面有不止一种观点吗?我只能看到您正在为页面设置一个文本视图 - 我已经让它工作了。当我想滚动 2 个文本视图时,我开始遇到问题。我也有点困惑,当布局包含许多视图时,它如何只膨胀到一个视图?
  • 事实上,你能不能把 XML 布局发给我看看,如果这不是太麻烦的话。非常感谢。
  • 查看 PagerAdapter 中的 isViewFromObject:如果我想在每页使用多个视图,是否需要进一步重写此方法以更完整地检查视图是否是返回对象的一部分?
  • 我已经添加了另外两个需要实现的方法。我的布局实际上有几个视图,为了简单起见,我只展示了一个。
  • 只是对新版本的修复...使用带有 ViewGroup 的 instantiateItem 而不是 View...它在上一个版本中已被贬值。
【解决方案2】:

我对这个适配器的工作原理有同样的误解,我已经做了一些调查。
关键的特殊性是您的视图存储在两个地方:
1 在 ViewPager 中调用((ViewPager) container).addView(view); 添加它们(这里你只需要存储三个视图,你所看到的和左右邻域)
2 在private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>(); 这是ViewPager 的成员,其中存储了包含有关它们位置信息的视图(通过调用适配器方法mAdapter.instantiateItem(this, position); 在此处添加它们)

static class ItemInfo {
    Object object;
    int position;
    boolean scrolling;
    float widthFactor;
    float offset;
}

当您滑动ViewPager 时,从mItems 数组中获取视图位置或对其进行实例化,并将此视图与ViewPager 的子视图与适配器方法public boolean isViewFromObject(View view, Object object) 进行比较。等于object 的视图在ViewPager 上显示给用户。如果没有视图,则显示空白屏幕。
这是ViewPager 方法,其中视图与对象进行比较:

ItemInfo infoForChild(View child) {
    for (int i=0; i<mItems.size(); i++) {
        ItemInfo ii = mItems.get(i);
        if (mAdapter.isViewFromObject(child, ii.object)) {
            return ii;
        }
    }
    return null;
}

如果来自 mItems 的视图位置不在 {currentposition -1,currentposition +1} 范围内,那么它将被销毁:

mItems.remove(itemIndex);
mAdapter.destroyItem(this, pos, ii.object);

ViewPagers 内存视图1

这是一个带有destroyItem 的陷阱,当您向前滑动时称为destroyItem 然后添加新项目,但是当您先向后滑动时添加新项目然后旧项目被销毁。如果您尝试只使用三个缓存视图,您可以在向后滑动时获得IllegalStateException: The specified child already has a parent.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-18
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    相关资源
    最近更新 更多