Android Appbarlayout和recyclerview的平滑滚动

Android Appbarlayout和recyclerview的平滑滚动,android,android-coordinatorlayout,Android,Android Coordinatorlayout,我想实现像谷歌Play应用程序一样的平滑滚动行为。我尝试过这里提到的解决方案: 但上述解决方案并没有像谷歌Play应用程序那个样给出预期的结果。 以下是xml代码: <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:a

我想实现像谷歌Play应用程序一样的平滑滚动行为。我尝试过这里提到的解决方案:

  • 但上述解决方案并没有像谷歌Play应用程序那个样给出预期的结果。 以下是xml代码:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layoutContent"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:background="@android:color/transparent"
        app:elevation="0dp">
    
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
    
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
                <View
                    android:id="@+id/view1"
                    android:layout_width="match_parent"
                    android:layout_height="125dp"
                    android:background="@android:color/transparent" />
    
                <android.support.v4.view.ViewPager
                    android:id="@+id/pager"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:fitsSystemWindows="true"
                    android:paddingLeft="24dp"
                    android:paddingRight="12dp" />
            </RelativeLayout>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_margin="@dimen/fab_margin"
        app:backgroundTint="@android:color/white"
        app:layout_anchor="@id/recycler_view"
        app:layout_anchorGravity="bottom|right|end"
        app:srcCompat="@drawable/ic_add_card" />
    </android.support.design.widget.CoordinatorLayout>
    
    
    
    如何实现平滑滚动

    编辑:这是recyclerview适配器

    class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewViewHolder> {
    private static final int DAYS_LEFT_TO_EXPIRE = 3;
    private CardCallback mCallback;
    private List<Ticket> mTickets;
    
    @Inject
    RecyclerViewAdapter() {
        mTickets = new ArrayList<>();
    }
    
    @Override
    public RecyclerViewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_card, parent, false);
        return new RecyclerViewViewHolder(view);
    }
    
    @Override
    public void onBindViewHolder(final RecyclerViewViewHolder holder, int position) {
        Ticket ticket = mTickets.get(position);
        if (ticket != null) {
            holder.setTicket(ticket);
            if (ticket.getHeadCount() != -1)
                holder.mTxtHeadCount.setText(String.valueOf(ticket.getHeadCount()));
            if (ticket.getType() != null && !ticket.getType().trim().isEmpty())
                setCardTitle(holder.mTxtCardTitle, ticket);
            if (ticket.getBlockCount() != -1)
                holder.mTxtBlockCount.setText(String.valueOf(ticket.getBlockCount()));
            if (ticket.getSeasonalPass() != null && !ticket.getSeasonalPass().trim().isEmpty())
                holder.mCardSeasonalPass.setText(ticket.getSeasonalPass());
            if (ticket.getLastUsedDate() != null)
                holder.mTxtCardLastUsedDate.setText(ticketDateFormatter.format(ticket.getLastUsedDate()));
            if (ticket.getExpiryDate() != null)
                holder.mTxtCardExpiryDate.setText(ticketDateFormatter.format(ticket.getExpiryDate()));
            if (ticket.getSeatingClass() != null && !ticket.getSeatingClass().trim().isEmpty())
                holder.mTxtSeatingClass.setText(ticket.getSeatingClass());
            if (ticket.getTheaterGroup() != null && !ticket.getTheaterGroup().trim().isEmpty())
                holder.mTxtTheaterGroup.setText(ticket.getTheaterGroup());
            if (ticket.getSellerName() != null && !ticket.getSellerName().trim().isEmpty())
                holder.mTxtSellerName.setText(ticket.getSellerName());
            if (ticket.getDescription() != null && !ticket.getDescription().trim().isEmpty())
                holder.mTxtCardDescription.setText(ticket.getDescription());
            if (ticket.getStatus() != null && !ticket.getStatus().trim().isEmpty())
                holder.mTxtCardStatus.setText(ticket.getStatus());
            if (DateUtil.noOfDaysLeft(ticket.getExpiryDate()) <= DAYS_LEFT_TO_EXPIRE)
                holder.mLblWarningMessage.setVisibility(View.VISIBLE);
            else holder.mLblWarningMessage.setVisibility(View.GONE);
            setCardProgress(holder.mCardProgress, ticket);
        }
    }
    
    private void setCardTitle(TextView txtCardTitle, Ticket ticket) {
        switch (ticket.getType()) {
            case Constants.CARD_TYPE_PACK:
                txtCardTitle.setText(ticket.getPackCount() + " " + ticket.getType());
                break;
            case Constants.CARD_TYPE_SEASONAL:
                txtCardTitle.setText(ticket.getType().concat(" pass"));
                break;
            default:
                txtCardTitle.setText(ticket.getType());
                break;
        }
    }
    
    private void setCardProgress(ProgressBar progressBar, Ticket ticket) {
        int maxLimit = 0, progress = 0;
        switch (ticket.getType()) {
            case Constants.CARD_TYPE_SEASONAL:
                maxLimit = (int) TimeUnit.MILLISECONDS.toDays(ticket.getExpiryDate().getTime() - ticket.getLastUsedDate().getTime());
                progress = maxLimit - DateUtil.noOfDaysLeft(ticket.getExpiryDate());
                break;
            case Constants.CARD_TYPE_PACK:
                maxLimit = ticket.getPackCount();
                progress = maxLimit - (ticket.getPackCount() - ticket.getPackUsed());
                break;
            case Constants.CARD_TYPE_TICKET:
                maxLimit = (int) TimeUnit.MILLISECONDS.toDays(ticket.getExpiryDate().getTime() - ticket.getTicketBoughtDate().getTime());
                progress = maxLimit - DateUtil.noOfDaysLeft(ticket.getExpiryDate());
                break;
        }
        progressBar.setMax(maxLimit);
        if (progress < 0) {
            progressBar.setProgress(maxLimit);
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
                progressBar.setProgress(progress, true);
            else progressBar.setProgress(progress);
        }
    }
    
    @Override
    public int getItemCount() {
        return mTickets.size();
    }
    
    void setTickets(List<Ticket> tickets) {
        if (tickets != null && !tickets.isEmpty()) {
            mTickets.addAll(tickets);
            notifyDataSetChanged();
        }
    }
    
    void setCallback(CardCallback callback) {
        this.mCallback = callback;
    }
    
    void clearTicketList() {
        mTickets.clear();
        notifyItemRangeChanged(0, mTickets.size());
    }
    
    interface CardCallback {
        void onBtnMoreCardInfoClicked(Ticket ticket, LinearLayout layout, ImageButton imageButton);
    }
    
    class RecyclerViewViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.txt_head_count)
        TextView mTxtHeadCount;
        @BindView(R.id.txt_card_type)
        TextView mTxtCardTitle;
        @BindView(R.id.txt_block_count)
        TextView mTxtBlockCount;
        @BindView(R.id.txt_seasonal_pass)
        TextView mCardSeasonalPass;
        @BindView(R.id.txt_card_last_used_date)
        TextView mTxtCardLastUsedDate;
        @BindView(R.id.txt_card_expiry_date)
        TextView mTxtCardExpiryDate;
        @BindView(R.id.card_progress)
        ProgressBar mCardProgress;
        @BindView(R.id.txt_seating_class)
        TextView mTxtSeatingClass;
        @BindView(R.id.txt_theater_group)
        TextView mTxtTheaterGroup;
        @BindView(R.id.txt_seller_name)
        TextView mTxtSellerName;
        @BindView(R.id.btn_more_card_info)
        ImageButton mBtnMoreCardInfo;
        @BindView(R.id.layout_card_description)
        LinearLayout mLayoutCardDescription;
        @BindView(R.id.txt_card_description)
        TextView mTxtCardDescription;
        @BindView(R.id.txt_card_status)
        TextView mTxtCardStatus;
        @BindView(R.id.lbl_warning_message)
        TextView mLblWarningMessage;
    
        private Ticket mTicket;
    
        NFCCardRecyclerViewViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
    
            mBtnMoreCardInfo.setOnClickListener(v -> {
                if (mCallback != null)
                    mCallback.onBtnMoreCardInfoClicked(mTicket, mLayoutCardDescription, mBtnMoreCardInfo);
            });
        }
    
        void setTicket(Ticket mTicket) {
            this.mTicket = mTicket;
        }
    }
    
    类RecycleServiceAdapter扩展了RecycleView.Adapter{ 私有静态最后整数天剩余到期天数=3; 私人卡回拨; 私人名单; @注入 RecycleServiceAdapter(){ mTickets=newarraylist(); } @凌驾 公共RecycleServiceViewHolder onCreateViewHolder(视图组父级,int-viewType){ View=LayoutFlater.from(parent.getContext()).flate(R.layout.row\u卡,parent,false); 返回新的RecyclerViewHolder(视图); } @凌驾 BindViewHolder上的公共无效(最终回收视图持有人,内部位置){ 票证=mTickets.get(位置); 如果(票证!=null){ 持票人:票(票); if(ticket.getHeadCount()!=-1) holder.mTxtHeadCount.setText(String.valueOf(ticket.getHeadCount()); if(ticket.getType()!=null&&!ticket.getType().trim().isEmpty()) setCardTitle(holder.mTxtCardTitle,票证); if(ticket.getBlockCount()!=-1) holder.mTxtBlockCount.setText(String.valueOf(ticket.getBlockCount()); if(ticket.getSeasonalPass()!=null&!ticket.getSeasonalPass().trim().isEmpty()) holder.mCardSeasonalPass.setText(ticket.getSeasonalPass()); if(ticket.getLastUsedDate()!=null) holder.mTxtCardLastUsedDate.setText(ticketDateFormatter.format(ticket.getLastUsedDate()); if(ticket.getExpiryDate()!=null) holder.mTxtCardExpiryDate.setText(ticketDateFormatter.format(ticket.getExpiryDate()); if(ticket.getSeatingClass()!=null&!ticket.getSeatingClass().trim().isEmpty()) holder.mTxtSeatingClass.setText(ticket.getSeatingClass()); if(ticket.getTheaterGroup()!=null&&!ticket.getTheaterGroup().trim().isEmpty()) holder.mTxtTheaterGroup.setText(ticket.getTheaterGroup()); if(ticket.getSellerName()!=null&!ticket.getSellerName().trim().isEmpty()) holder.mTxtSellerName.setText(ticket.getSellerName()); if(ticket.getDescription()!=null&&!ticket.getDescription().trim().isEmpty()) holder.mTxtCardDescription.setText(ticket.getDescription()); if(ticket.getStatus()!=null&&!ticket.getStatus().trim().isEmpty()) holder.mTxtCardStatus.setText(ticket.getStatus()); if(DateUtil.noOfDaysLeft(ticket.getExpiryDate())=Build.VERSION\u code.N) progressBar.setProgress(progress,true); else progressBar.setProgress(进度); } } @凌驾 public int getItemCount(){ 返回mTickets.size(); } 作废票证(列出票证){ if(tickets!=null&!tickets.isEmpty()){ mTickets.addAll(票); notifyDataSetChanged(); } } void setCallback(CardCallback){ this.mCallback=回调; } 作废clearTicketList(){ mTickets.clear(); notifyItemRangeChanged(0,mTickets.size()); } 接口卡回调{ 作废已单击的BTNMoreCardInfo(票证、线性布局布局、图像按钮); } 类RecyclerViewHolder扩展了RecyclerView.ViewHolder{ @BindView(R.id.txt\u head\u count) text查看mtxt员工总数; @BindView(R.id.txt\u卡类型) 文本视图mTxtCardTitle; @BindView(R.id.txt\u块\u计数) TextView mTxtBlockCount; @BindView(R.id.txt\u季节性\u通行证) TextView mCardSeasonalPass; @BindView(R.id.txt\u卡片\u上次使用\u日期) TextView mTxtCardLastUsedDate; @BindView(R.id.txt\u卡\u到期日期) TextView mTxtCardExpiryDate; @BindView(R.id.card\u进度) ProgressBar-mCardProgress; @BindView(R.id.txt\u seating\u class) 文本视图mTxtSeatingClass; @BindView(R.id.txt\u剧院组) 文本视图mTxtTheaterGroup; @BindView(R.id.txt\u卖方名称) TextView mTxtSellerName; @BindView(R.id.btn\u更多\u卡\u信息) 图像按钮mBtnMoreCardInfo; @BindView(R.id.布局\卡\说明) 线性布局mLayoutCardDescription; @BindView(R.id.txt\u卡\u说明) 文本视图mTxtCardDescription; @BindView(R.id.txt\u卡\u状态) text查看mTxtCardStatus; @BindView(R.id.lbl\u警告消息) 文本视图mLblWarningMessage; 私人机票; NFCCardRecycleServiceViewHolder(查看项目视图){ 超级(项目视图); ButterKnife.bind(这个,itemView); mBtnMoreCardInfo.setOnClickListener(v->{ 如果(mCallback!=null) 单击mCallback.onBTNMoreCardInfo(mTicket、mLayoutCardDescription、mBtnMoreCardInfo); }); } 无效设置票证(票证mTicket){ this.mTicket=mTicket; } }
    }

    遵循此链接上的步骤:
    此库帮助我解决了问题。

    发布您的RecyclerView适配器。可能是适配器有问题@배준모 请检查编辑