henrytao-me / smooth-app-bar-layout

Smooth version of Google Support Design AppBarLayout
Apache License 2.0
1.77k stars 240 forks source link

appbarlayout gets dissappeared #203

Closed Shrikant-B closed 7 years ago

Shrikant-B commented 7 years ago

I'm using smoothappbar layout for smoothly scrolling recyclerview and appbarlayout. I followed all three steps mentioned still i'm getting result as in video in below link. Result

Here is code for 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"/>

    <me.henrytao.smoothappbarlayout.SmoothAppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:background="@android:color/transparent"
        app:elevation="0dp"
        app:sabl_target_id="@id/recycler_view">

        <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"
                app:layout_collapseMode="pin">

                <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>
    </me.henrytao.smoothappbarlayout.SmoothAppBarLayout>

    <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>
henrytao-me commented 7 years ago

Hi @ShrikantBadwaik-007

I don't see any issues in your layout. Does your RecyclerView have first ViewHolder with 250dp in height? Can you change RecyclerView to NestedScrollView and see what happen? Ex:

<?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.v4.widget.NestedScrollView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent">

        <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:orientation="vertical"
          android:paddingLeft="16dp"
          android:paddingRight="16dp"
          android:paddingTop="250dp">

          <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:layout_marginTop="16dp"
            android:text="@string/text_short" />

          <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:text="@string/text_long" />
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

    <me.henrytao.smoothappbarlayout.SmoothAppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:background="@android:color/transparent"
        app:elevation="0dp"
        app:sabl_target_id="@id/recycler_view">

        <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"
                app:layout_collapseMode="pin">

                <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>
    </me.henrytao.smoothappbarlayout.SmoothAppBarLayout>

    <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>
Shrikant-B commented 7 years ago

@henrytao-me i have added a header of height same as height of appbarlayout. Are you suggesting some like this:

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>

This is my adapter:

class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    private static final int DAYS_LEFT_TO_EXPIRE = 3;
    private List<Ticket> mTickets;

@Inject
RecyclerViewAdapter() {
    mTickets = new ArrayList<>();
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_HEADER) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_card_header, parent, false);
        return new HeaderViewHolder(view);
    } else if (viewType == TYPE_ITEM) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_card, parent, false);
        return new NFCCardRecyclerViewViewHolder(view);
    }
    throw new RuntimeException("No match for: " + viewType);
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof RecyclerViewViewHolder) {
        RecyclerViewViewHolder viewHolder = (RecyclerViewViewHolder) holder;
        Ticket ticket = mTickets.get(position - 1);
        if (ticket != null) {
            viewHolder.setTicket(ticket);
            if (ticket.getHeadCount() != -1)
                viewHolder.mTxtHeadCount.setText(String.valueOf(ticket.getHeadCount()));
            if (ticket.getType() != null && !ticket.getType().trim().isEmpty())
                setCardTitle(viewHolder.mTxtCardTitle, ticket);
            if (ticket.getBlockCount() != -1)
                viewHolder.mTxtBlockCount.setText(String.valueOf(ticket.getBlockCount()));
            if (ticket.getSeasonalPass() != null && !ticket.getSeasonalPass().trim().isEmpty())
                viewHolder.mCardSeasonalPass.setText(ticket.getSeasonalPass());
            if (ticket.getLastUsedDate() != null)
                viewHolder.mTxtCardLastUsedDate.setText(ticketDateFormatter.format(ticket.getLastUsedDate()));
            if (ticket.getExpiryDate() != null)
                viewHolder.mTxtCardExpiryDate.setText(ticketDateFormatter.format(ticket.getExpiryDate()));
            if (ticket.getSeatingClass() != null && !ticket.getSeatingClass().trim().isEmpty())
                viewHolder.mTxtSeatingClass.setText(ticket.getSeatingClass());
            if (ticket.getTheaterGroup() != null && !ticket.getTheaterGroup().trim().isEmpty())
                viewHolder.mTxtTheaterGroup.setText(ticket.getTheaterGroup());
            if (ticket.getSellerName() != null && !ticket.getSellerName().trim().isEmpty())
                viewHolder.mTxtSellerName.setText(ticket.getSellerName());
            if (ticket.getDescription() != null && !ticket.getDescription().trim().isEmpty())
                viewHolder.mTxtCardDescription.setText(ticket.getDescription());
            if (ticket.getStatus() != null && !ticket.getStatus().trim().isEmpty())
                viewHolder.mTxtCardStatus.setText(ticket.getStatus());
            if (DateUtil.noOfDaysLeft(ticket.getExpiryDate()) <= DAYS_LEFT_TO_EXPIRE)
                viewHolder.mLblWarningMessage.setVisibility(View.VISIBLE);
            else viewHolder.mLblWarningMessage.setVisibility(View.GONE);
            setCardProgress(viewHolder.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() + 1;
}

@Override
public int getItemViewType(int position) {
    if (position == 0) return TYPE_HEADER;
    return TYPE_ITEM;
}

void setTickets(List<Ticket> tickets) {
    if (tickets != null && !tickets.isEmpty()) {
        mTickets.addAll(tickets);
        notifyDataSetChanged();
    }
}

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;
    }
}

class HeaderViewHolder extends RecyclerView.ViewHolder {
    HeaderViewHolder(View itemView) {
        super(itemView);
    }
}

As you can see i have added a header at 0th position.

henrytao-me commented 7 years ago

Hi @ShrikantBadwaik-007

I didn't suggest to add RecyclerView inside NestedScrollView. My previous comment says that try to test scrolling behavior with NestedSrollView only. If the problem does not exist in NestedScrollView, then try to figure out why it is happened in RecyclerView (check RecyclerView for example). As I can see, you set header in RecyclerView already. Hmmmmmmmm.