【问题标题】:Cannot get sticky headers to work with SuperSLiM无法让粘性标题与 SuperSLiM 一起使用
【发布时间】:2015-10-06 19:46:38
【问题描述】:

我正在尝试在我已经存在的RecyclerView 中实现粘性标头,它有标头,但没有标头。 SuperSLiM 看起来很有希望,但我无法将该库集成到我现有的代码中。源代码后面的示例运行良好,我已经尝试适应这一点并按照SuperSLiM wiki 上的步骤进行操作。

我的RecyclerView 最初是空的。我遇到的问题是当我第一次将项目添加到我的适配器并在这些项目上调用 Adapter.notifyItemChanged() 时。完成此操作后,我会被扔进LayoutManager.onItemsUpdated()。该方法如下所示:

public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount)
{
    super.onItemsUpdated(recyclerView, positionStart, itemCount);
    View first = this.getChildAt(0);                        // null
    View last = this.getChildAt(this.getChildCount() - 1);  // null
    if(positionStart + itemCount > this.getPosition(first)) // NullPointerException
    {
        if(positionStart <= this.getPosition(last))
        {
            this.requestLayout();
        }

    }
}

在这里,firstlast 都变为 null,因此在下面的行中抛出了 NullPointerException。请注意,onItemsUpdated() 在示例应用程序中没有调用,因此此处不会发生此错误。我不知道为什么; Adapter.notifyItemChanged() 在示例应用中也被调用。

可能是什么问题?

我的片段类:

请注意,在下面的代码中切换回正常的RecyclerView.LayoutManager 会使一切正常工作。

public class MyFragment extends Fragment
{
    private MyRecyclerView      mRecyclerView;
    private MyAdapter           mAdapter;

//  private RecyclerView.LayoutManager      mLayoutManager; // Normal RecyclerView.LayoutManager working just fine
    private LayoutManager                   mLayoutManager; // SuperSLiM LayoutManager crashing

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        View rootView = inflater.inflate(R.layout.my_fragment, container, false);
        MyActivity myActivity = (MyActivity) rootView.getContext();

        mRecyclerView = (MyRecyclerView) rootView.findViewById(R.id.my_recyclerview);

//      mLayoutManager = new LinearLayoutManager(myActivity); // Normal RecyclerView.LayoutManager
        mLayoutManager = new LayoutManager(myActivity);       // SuperSLiM LayoutManager
        mAdapter = new MyAdapter(myActivity);

        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mAdapter);

        myActivity.onShoppingListCreated();
        return rootView;
    }

    public void onDataSetChanged()
    {
        if (mAdapter == null)
        {
            return;
        }
        mAdapter.notifyDataSetChanged();
    }

    // This is called multiple times after a button press at some point.
    // Thereafter, if it is the SuperSLiM LayoutManager that is in play,
    // the error explained above occurs.
    public void onItemChanged(int position)
    {
        if (mAdapter == null)
        {
            return;
        }
        mAdapter.notifyItemChanged(position);
    }
}

崩溃时的堆栈跟踪:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference
            at android.support.v7.widget.RecyclerView$LayoutManager.getPosition(RecyclerView.java:6097)
            at com.tonicartos.superslim.LayoutManager.onItemsUpdated(LayoutManager.java:542)
            at android.support.v7.widget.RecyclerView$5.dispatchUpdate(RecyclerView.java:665)
            at android.support.v7.widget.RecyclerView$5.onDispatchSecondPass(RecyclerView.java:675)
            at android.support.v7.widget.AdapterHelper.consumeUpdatesInOnePass(AdapterHelper.java:547)
            at android.support.v7.widget.RecyclerView.processAdapterUpdatesAndSetAnimationFlags(RecyclerView.java:2530)
            at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2318)
            at android.view.View.measure(View.java:17547)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:875)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
            at android.view.View.measure(View.java:17547)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1488)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
            at android.view.View.measure(View.java:17547)
            at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
            at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
            at android.view.View.measure(View.java:17547)
            at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:868)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
            at android.support.v7.internal.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:124)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2615)
            at android.view.View.measure(View.java:17547)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventRe

【问题讨论】:

    标签: android android-recyclerview superslim


    【解决方案1】:

    这些天我不得不做类似的事情,我使用了这个库:https://github.com/timehop/sticky-headers-recyclerview

    如果你习惯了 RecyclerViews 适配器,这很容易。

    【讨论】:

    • 是的,我也看过那个库。我不相信我可以使用它,因为它的文档指出:标题视图被绘制到画布上,实际上并不是视图层次结构的一部分。因此,它们不能有触摸状态,如果您尝试将图像异步加载到它们中,您可能会遇到问题。。在我的例子中,除了纯文本之外,标题还需要有一些状态和额外的视图(例如一个小按钮)。我想这个库是不可能的。如果我错了,请纠正我。
    • @Krøllebølle,你是完全正确的,确实我在我的github.com/davideas/FlexibleAdapter 项目中使用了相同的 timehop​​ 机制,我正在寻找帮助以使用自定义 LayoutManager 以良好的方式制作粘性标题,没有SuperSlim 项目完成后的大量编码(仅部分和粘性标题约 3400 行!?)
    【解决方案2】:

    将此行添加到 onBindViewHolder 方法的末尾:

     //configuring sticky headers
        final LayoutManager.LayoutParams lp = LayoutManager.LayoutParams.from(holder.itemView.getLayoutParams());
        lp.setSlm(LinearSLM.ID);
        lp.setFirstPosition(getHeaderPosition(position));
        holder.itemView.setLayoutParams(lp);
    

    getHeaderPosition 方法返回每个项目的标题位置

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-31
      • 2018-01-02
      • 2016-11-14
      • 2015-02-01
      • 2019-05-10
      • 2017-11-20
      • 2011-05-24
      相关资源
      最近更新 更多