Android Appbarlayout和recyclerview的平滑滚动
我想实现像谷歌Play应用程序一样的平滑滚动行为。我尝试过这里提到的解决方案: 但上述解决方案并没有像谷歌Play应用程序那个样给出预期的结果。 以下是xml代码: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
<?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适配器。可能是适配器有问题@배준모 请检查编辑