Issue
I have a very basic yet difficult issue where I have a button fixed at the bottom of the view, but below recyclerview container. Once the container size grows, I want the button to go below the recyclerview (scrollable) instead of being fixed at the bottom of the view.Is there a way to achieve this?
I have looked online for a couple of ideas but didn't find anything quite like it yet.
i am basically using
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:clickable="false">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/cl_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false">
<LinearLayout
android:id="@+id/activity_g"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:subtitleTextColor="@color/white"
app:titleTextAppearance="@style/Toolbar.TitleText"
app:titleTextColor="@color/white">
<TextView
android:id="@+id/nav_back_btn"
style="@style/Body1RegLeftBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:gravity="center_horizontal"
android:background="@drawable/ic_backarrow" />
<TextView
android:id="@+id/g_main_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="15dp"
android:letterSpacing="0.01"
android:gravity="center_horizontal"
android:text="@string/g"
android:textAppearance="@style/TextAppearance.Text.Roboto.Medium"
android:textColor="#de000000"
android:textSize="20sp"
android:textStyle="normal"
/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/info_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/infoContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:clickable="false"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp">
<TextView
android:id="@+id/info_location"
style="@style/Headline2LeftBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:textAppearance="@style/TextAppearance.Text.Chronicle"
android:textSize="28sp"
tools:text="@string/five_thirty_fifth_ave" />
<TextView
style="@style/Body1RegRightRed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/info_location"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_toEndOf="@+id/info_location"
android:text="@string/location_change"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:visibility="gone" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="44dp"
android:gravity="center_vertical"
android:weightSum="2">
<TextView
style="@style/Body1RegLeftBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:id="@+id/g_start_date"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:text="@string/g_start_date" />
<TextView
style="@style/Body1RegRightBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:id="@+id/g_start_time"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:text="@string/g_start_time" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/registerUserSeparatorColor" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:weightSum="2">
<TextView
style="@style/Body1RegLeftBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:id="@+id/g_end_date"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:visibility="invisible"
android:text="@string/g_end_date" />
<TextView
style="@style/Body1RegRightBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:id="@+id/g_end_time"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:text="@string/g_end_time" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/registerUserSeparatorColor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="28dp"
android:letterSpacing="0.01"
android:lineSpacingExtra="4sp"
android:paddingTop="30dp"
android:textAppearance="@style/TextAppearance.Text.Roboto.Medium"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="normal"
android:text="@string/g" />
<android.support.v7.widget.RecyclerView
android:id="@+id/g_item_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"
android:divider="@null"
tools:listitem="@layout/item_g"/>
<TextView
style="@style/Body1RegLeftRed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16sp"
android:layout_marginTop="20dp"
android:id="@+id/add_g"
android:lineHeight="22sp"
android:text="@string/add_g"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="58dp"
android:letterSpacing="0.01"
android:lineSpacingExtra="4sp"
android:visibility="invisible"
android:textAppearance="@style/TextAppearance.Text.Roboto.Medium"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="normal"
android:text="@string/arrival_notifications" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:id="@+id/text_message_container"
android:layout_marginStart="16dp">
<TextView
android:id="@+id/text_message"
style="@style/Body1RegLeftBlack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="11dp"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:text="@string/text_message" />
<TextView
style="@style/Body2RegLeftGrey"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/text_message"
android:layout_marginTop="2dp"
android:id="@+id/tap_phone_number_text"
android:textAppearance="@style/TextAppearance.Text.Roboto.Regular"
android:text="@string/tap_to_add_a_phone_number" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/text_message_switch"
style="@style/Color1SwitchStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="16dp"
android:visibility="gone"
android:layout_marginTop="11dp"
android:background="@color/settingsSeparatorLineColor" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_marginTop="100dp"
android:textAppearance="@style/TextAppearance.Text.Roboto.Medium"
android:textStyle="normal"
android:letterSpacing="0.07"
android:lineSpacingExtra="0sp"
android:layout_gravity="center"
android:layout_marginBottom="30dp"
android:id="@+id/submit_btn"
android:text="@string/submit_list"
/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>
The problem above is, the submit_list btn doesnt stay fixed, if the recyclerview grows but theres still enough space to spare in the view.
I want to make it such that the button stays fixed and doesnt scroll UNTIL the size of the recyclerview goes beyond a certain limit from the bottom(not visible on the screen anymore), after which the button scrolls relative to the last item of the recyclerview and not aligned to the bottom anymore. any ideas how to go about it?
As you can see, initial screen has submit button aligned to the bottom and the rest of the content in place. As I add more users:
It still stays at the bottom since the recyclerview items are still within screen now, aqs soon as i add one more item, causing the list to scroll up :
As seen I want it to go below the recyclerview instead of stay fixed at bottom of the screen (the above screenshots are from ios where it works), was wondering if we can do the same for android?
Solution
This is a demo link
And a Gif link
public class WeirdStickyBottomActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private TextView mStickyView;
private LinearLayoutManager mLayoutManager;
private MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weird_sticky_bottom);
mRecyclerView = findViewById(R.id.recyclerview);
mStickyView = findViewById(R.id.sticky);
Button mAddButton = findViewById(R.id.button_add);
Button mDeleteButton = findViewById(R.id.button_delete);
mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
mAdapter = new MyAdapter(this);
mRecyclerView.setAdapter(mAdapter);
hideStickyLayoutIfNeed();
mAddButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAdapter.addItems();
hideStickyLayoutIfNeed();
}
});
mDeleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAdapter.deleteItems();
hideStickyLayoutIfNeed();
}
});
mStickyView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(WeirdStickyBottomActivity.this, "Sticky Click", Toast.LENGTH_SHORT).show();
}
});
}
private void hideStickyLayoutIfNeed() {
mRecyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mRecyclerView.getViewTreeObserver().removeOnPreDrawListener(this);
int firstVisible = mLayoutManager.findFirstVisibleItemPosition();
int lastCompletelyVisible = mLayoutManager.findLastCompletelyVisibleItemPosition();
//adapter list size display beyond the screen
if (firstVisible > 0 || lastCompletelyVisible < mAdapter.getItemCount() - 1) {
mAdapter.addStickyItem(true);
if (mStickyView.getVisibility() == View.VISIBLE) {
mStickyView.setVisibility(View.GONE);
}
} else if (firstVisible == 0 && lastCompletelyVisible == mAdapter.getItemCount() - 1) {
if (mStickyView.getVisibility() != View.VISIBLE) {
mStickyView.setVisibility(View.VISIBLE);
}
}
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
return true;
}
});
}
private static class MyAdapter extends RecyclerView.Adapter<ItemHolder> {
private int mStickyIndex = -1;
static final int HOLDER_TYPE_NORMAL = 1;
static final int HOLDER_TYPE_STICKY = 2;
private List<String> dataList = new ArrayList<>();
private Context mContext;
MyAdapter(Context context) {
this.mContext = context;
addItems();
}
public void addItems() {
boolean hasStickyItem = mStickyIndex > 0;
if (hasStickyItem) {
dataList.remove(mStickyIndex);
mStickyIndex = -1;
}
int size = dataList.size();
for (int i = size; i < size + 5; i++) {
dataList.add("This is a item");
}
notifyDataSetChanged();
}
public void deleteItems() {
int size = dataList.size();
if (size < 6) {
return;
}
boolean hasStickyItem = mStickyIndex > 0;
if (hasStickyItem) {
dataList.remove(mStickyIndex);
mStickyIndex = -1;
}
if (size > size - 5) {
dataList.subList(size - 5, size - 1).clear();
}
notifyDataSetChanged();
}
public void addStickyItem(boolean notify) {
//did not add sticky item before
if (mStickyIndex <= 0) {
mStickyIndex = dataList.size();
dataList.add(mContext.getResources().getString(R.string.sticky_layout));
if (notify) {
notifyDataSetChanged();
}
}
}
@NonNull
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return ItemHolder.create(parent, viewType == HOLDER_TYPE_STICKY);
}
@Override
public void onBindViewHolder(@NonNull ItemHolder holder, int position) {
holder.bind(dataList.get(position));
}
@Override
public int getItemCount() {
return dataList.size();
}
@Override
public int getItemViewType(int position) {
if (position == mStickyIndex) {
return HOLDER_TYPE_STICKY;
}
return HOLDER_TYPE_NORMAL;
}
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private TextView textView;
private boolean isSticky;
private ItemHolder(@NonNull View itemView, boolean isSticky) {
super(itemView);
textView = itemView.findViewById(R.id.text);
this.isSticky = isSticky;
}
void bind(String text) {
textView.setText(text);
if (isSticky) {
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Sticky Click", Toast.LENGTH_SHORT).show();
}
});
textView.setBackgroundColor(textView.getResources().getColor(R.color.colorPrimary));
} else {
textView.setOnClickListener(null);
textView.setBackgroundColor(Color.WHITE);
}
}
static ItemHolder create(ViewGroup parent, boolean isSticky) {
return new ItemHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, parent, false), isSticky);
}
}
}
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_behavior="android.support.design.widget.AppBarLayout$Behavior">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="Collapse">
<android.support.v7.widget.Toolbar
android:id="@+id/tb_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="@string/app_name">
<Button
android:id="@+id/button_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_add" />
<Button
android:id="@+id/button_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_delete" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/sticky_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/sticky"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="@string/sticky_layout" />
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
Answered By - Jeffery Ma
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.