【问题标题】:ListView ghosting when using DrawerLayout with Fragments将 DrawerLayout 与 Fragments 一起使用时出现 ListView 重影
【发布时间】:2013-06-15 16:18:36
【问题描述】:

在我将其切换为使用 DrawerLayout 中的片段之前,我的布局工作正常。之后,主视图中的 ListView 在滚动时会显示列表的副本。

ListView 内容滚动,但第一页的副本仍保留在屏幕上。我一直在记录调试消息,没有创建第二个 listview 副本,也没有从适配器发送第二个数据副本。

活动的布局在切换到片段之前使用带有片段的 DrawerLayout 它工作正常。

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="400dp"
    android:layout_height="800dp">

<!-- The main content view -->
<fragment android:name="com.nosweatbudgets.receipts.ReceiptsFragment"
          android:id="@+id/receipts_fragment"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
        />

<!-- The navigation drawer -->
<fragment android:name="com.nosweatbudgets.navigate.NavigateFragment"
          android:id="@+id/navigate_fragment"
          android:layout_width="300dp"
          android:layout_height="match_parent"
          android:layout_gravity="start"
        />

</android.support.v4.widget.DrawerLayout>

每个片段类都非常简单。

ReceiptsFragment 的 onCreateView 长这样。

    View view = inflater.inflate(R.layout.receipts, container, false);

    _adapter = new ReceiptsAdapter(inflater);
    ListView list = (ListView) view.findViewById(R.id.receipt_list);
    list.setAdapter(_adapter);
    _adapter.Refresh();

    return view;

NavigateFragment 的 onCreateView 与不同的适配器基本相同。是 ReceiptsFragment 出现重影,而 NavigateFragment 没有重影。然而,他们可以采用基本相同的方法。

    View view = inflater.inflate(R.layout.navigate, container, false);

    _navigate = new NavigateAdapter(inflater);
    // setup the list view for the side
    ListView list = (ListView) view.findViewById(R.id.left_drawer);
    list.setAdapter(_navigate);
    _navigate.Refresh();

    return view;

对于上述片段类,我使用以下布局。

receipts.xml 看起来像这样。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/receipt_list"/>
</RelativeLayout>

navigate.xml 看起来像这样。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<ListView
        android:id="@+id/left_drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:choiceMode="singleChoice"
        android:background="#EEEEEE"/>
</RelativeLayout>

拉出导航列表视图工作正常,但主收据列表视图有重影问题。

我完全不知道是什么原因造成的。

编辑

这是在ReceiptsAdapter 中创建视图的方式。

public View getView(int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    if (view == null)
    {
        view = _inflater.inflate(R.layout.receipt, null);
    }

    TextView txt_vendor = (TextView) view.findViewById(R.id.receipt_vendor);
    TextView txt_category = (TextView) view.findViewById(R.id.receipt_category);
    TextView category_btn = (TextView) view.findViewById(R.id.category_btn);

    Model receipt = _receipts.get(position);

    int vendor_id = receipt.getAsInteger("smart_vendor_id");
    int category_id = receipt.getAsInteger("smart_category_id");


    if (_vendors.indexOfKey(vendor_id) >= 0)
    {
        txt_vendor.setText(_vendors.get(vendor_id));
    }
    else
    {
        txt_vendor.setText("Select Vendor");
    }

    if (_categories.indexOfKey(category_id) >= 0)
    {
        String cat = _categories.get(category_id);
        txt_category.setText(cat);
        category_btn.setText(Category.ShortTitle(cat));
        category_btn.setBackgroundColor(Category.Color(cat));
        //txt_category.setBackgroundColor(c);
    }
    else
    {
        txt_category.setText("Select Category");
        category_btn.setText("N/A");
    }

    ((TextView) view.findViewById(R.id.receipt_amount)).setText("$" + receipt.getAsString("amount"));
    ((TextView) view.findViewById(R.id.receipt_payment)).setText(receipt.getAsString("payment"));
    ((TextView) view.findViewById(R.id.receipt_date)).setText(receipt.getAsString("receipt_date"));

    return view;
}

编辑

这是布局的 Activity 通过onCreate 方法附加片段的方式。

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    // the layout uses fixed width/size, because the layout editor won't render match_parent.
    // so I replace the layout parameters here with match_parent.
    DrawerLayout layout = (DrawerLayout) getLayoutInflater().inflate(R.layout.main, null);
    DrawerLayout.LayoutParams param = new DrawerLayout.LayoutParams(ViewGroup.LayoutParams
            .MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    layout.setLayoutParams(param);
    setContentView(layout);

    // configure this activity
    StyleActionBar();

    // Add the fragments
    getSupportFragmentManager().beginTransaction()
            .add(R.id.navigate_fragment, new NavigateFragment())
            .add(R.id.receipts_fragment, new ReceiptsFragment())
            .commit();
}

【问题讨论】:

  • 只是为了确认我对您的理解正确:当您点击打开抽屉时,您会看到NavigateFragment 分层在ReceiptsFragment 之上?但是当抽屉关闭时(打开抽屉之前或关闭之后),你只会看到ReceiptsFragment?
  • 我们可以从适配器中看到getView方法吗?如果可能,也可以刷新一个。
  • @CommonsWare 嗨,你是对的。 NavigateFragment 是你从左侧滑出的隐藏视图,ReceiptsFragment 是始终可见的主视图。
  • @NeronT 我将 getView 添加到问题中。 Refresh 方法调用 JSON 服务来创建收据记录的ArrayList。导航和收据都使用相同的底层 JSON 代码,但导航不会重影,所以我认为这不是问题。
  • 您可以尝试将NavigateFragment 切换为通过FragmentTransaction 创建的动态片段。通过&lt;fragment&gt; 标记的静态片段应该始终存在,并且“永远存在”部分可能会破坏DrawerLayout 逻辑。

标签: android android-listview


【解决方案1】:

我错误地遵循了片段教程,在布局 XML 中创建了一个静态片段,并在运行时为同一类创建了一个动态片段。

主布局使用&lt;fragment&gt; 标记创建一个片段,该片段在运行时通过android:name 属性自动附加。

这就是我的layout.xml中的内容

<fragment android:name="com.nosweatbudgets.receipts.ReceiptsFragment"
          android:id="@+id/receipts_fragment"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
        />

这足以创建片段,但我错误地在我的活动中添加了片段教程中的代码,如下所示。

    getSupportFragmentManager().beginTransaction()
            .add(R.id.navigate_fragment, new NavigateFragment())
            .add(R.id.receipts_fragment, new ReceiptsFragment())
            .commit();

这在运行时向 Activity 添加了两个额外的片段视图。这导致相同位置的两个列表视图。

看起来像是幻影神器的东西实际上是同一职业的两个碎片在彼此之上。删除 onCreate 中的动态创建解决了我的问题。

【讨论】:

  • 这进一步验证了木工的百年规则:“测量两次。实例化碎片一次。”或者类似的东西...... :-)
  • @cgTag 五年后,我做了同样的事情......谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-25
  • 2015-10-29
  • 2018-07-12
  • 1970-01-01
相关资源
最近更新 更多