This is my layout xml:
<RelativeLayout 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:background="#color/fragment_body"
android:fitsSystemWindows="true">
<include
android:id="#+id/contextToolBar"
layout="#layout/context_toolbar_layout" />
<android.support.v7.widget.RecyclerView
android:id="#+id/list1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/contextToolBar"
android:scrollbarSize="5dp"
android:scrollbarThumbVertical="#color/scrollbarColor"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<ProgressBar
android:id="#+id/delete_progress"
style="#style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="gone" />
It displays a grid of images in the recyclerview.
I can select a bunch of images & have an option to delete them.
The following is the delete logic:
public void deleteSelectedFiles(final Context context, final List<MediaModel> selectionList) {
String confirmationMessage = getString(R.string.delete_confirm_message);
new AlertDialog.Builder(context)
.setTitle(getString(R.string.action_delete))
.setMessage(confirmationMessage)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.yes, (dialog, whichButton) -> {
View progressBar = getActivity().findViewById(R.id.delete_progress);
dialog.cancel();
progressBar.setVisibility(View.VISIBLE);
deleteFileList(selectionList, this.getActivity());
progressBar.setVisibility(View.GONE);
})
.setNegativeButton(android.R.string.no, null).show();
}
I am expecting the progress bar to display in the foreground while the delete operation is going on. But it just doesn't show up. Any help would be highly appreciated.
So I had this problem before. In my case it was because I was using a Material Design Theme for the whole app, so I had to use a specific orientation and it solved my problem. You can try with
<ProgressBar
android:id="#+id/progressBarReady"
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:indeterminate="true"
android:visibility="visible"/>
I had a similar problem. In my case, I was using a ProgressBar as a loading indicator inside a CoordinatorLayout.
In the Activity/Fragment - at different points - based on the data becoming available - ie using a Cursor or from the Network, I needed to call
mViewA.setVisibility(View.GONE)
or mViewB.setVisibility(View.VISIBLE).
When I set these up correctly for my views including the ProgressBar View, it became visible.
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
style="?android:attr/progressBarStyle" is what fixed it for me.
Related
Here is my Persistent BottomSheet
<androidx.constraintlayout.widget.ConstraintLayout 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/bs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bottom_sheet_background"
android:elevation="2dp"
android:padding="#dimen/base_margin"
app:behavior_hideable="true"
app:behavior_peekHeight="#dimen/bottom_sheet_peek_height"
app:layout_behavior="#string/bottom_sheet_behavior">
When User scrolls RecycleView, BottomNavigation hides and I reduce height of BottomSheet accordingly in RecycleView's addOnScrollListener using:
binding.rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
//148 = 80(bottom navigation) + 56(bottom sheet)
if (dy < 0)//scroll down
bottomSheetBehavior.setPeekHeight(136, true);
else if (dy > 0)//scroll up
bottomSheetBehavior.setPeekHeight(56, true);
}
After BottomNavigation is hidden and BottomSheet height is reduced, if BottomSheet is clickable,
(either through code binding.bs.bs.setClickable(false); or through xml android:clickable="true")
I can't drag it to expand. If it is not clickable, click event goes through it and user click on RecycleView item underneath it.
Even when its height is not reduced and it isn't clickable then also click event goes under it and fire on RecycleView item.
I also tried setting nestedScrolling, which allowed expanding but after that start creating issues when collapsing. :(
UPDATE:
I noticed BottomSheet drag not works when I set Bottomsheet clickable and its peekheight < 80 dp, ie the height of BottomNavigation.
Reference:
Why am I able to click "behind" the bottomsheet in Android?
I had same use case of having a recycler view inside a bottom sheet and here's what my Bottom sheet XML looks like. Please try to check if this works for you!
Apart from this, I did not actually get it why you want to reduce the height of the bottom sheet, as Bottom sheet has the behavior of self adjusting its height respect to the content inside it.
Please if possible share your use case so that it will be easier for the community to answer which gonna hit the bonsai. Thanks!
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:background="#color/transparent"
android:layout_height="match_parent"
android:paddingTop="50dp"
android:id="#+id/rootLayout"
>
<include
android:id="#+id/progress"
layout="#layout/item_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="#+id/rootView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/bottom_sheet_rounded_background"
android:backgroundTint="#color/background_gray"
android:clipToPadding="true"
android:orientation="vertical"
app:layout_behavior="#string/bottom_sheet_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<RelativeLayout
android:id="#+id/title_rl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:height="24sp"
android:fontFamily="#font/silka_bold"
android:text="#string/error_select_prescription"
android:textColor="#color/text_color_semi_black"
android:textSize="16sp" />
<ImageView
android:id="#+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
android:src="#drawable/ic_close_btn_gray" />
</RelativeLayout>
<View
android:id="#+id/view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/btn_gray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/title_rl" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerViewPrescription"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingTop="#dimen/dimen_16dp"
tools:itemCount="10" />
</androidx.core.widget.NestedScrollView>
<include
android:id="#+id/btn_select_and_proceed"
layout="#layout/sticky_footer_design_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
val bottomSheet = dialog!!.findViewById<View>(R.id.design_bottom_sheet) as FrameLayout
val behavior: BottomSheetBehavior<*> = BottomSheetBehavior.from<View>(bottomSheet)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
These all are the states which you can use to manipulate the height or basically the behavior of the BottomSheet.
So I have the coordinate layout as the root layout as I am using a floating Action button.
Here is my xml.
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:context=".activities.teacher.TeacherJobBoard"
android:id="#+id/rootLayout_job_board"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/anchor"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/color_black_darker_overlay"
android:layout_gravity="bottom"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/all_night_background"
android:orientation="vertical"
tools:context=".activities.teacher.TeacherJobBoard">
<com.hugocastelani.waterfalltoolbar.WaterfallToolbar
android:id="#+id/teacher_job_board_waterfall_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:final_elevation="15dp">
<androidx.appcompat.widget.Toolbar
android:id="#+id/teacher_job_board_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/tutor_bear_dark_blue"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme" />
</com.hugocastelani.waterfalltoolbar.WaterfallToolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/discretescrollview_teacherJobBoard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>
<com.github.ybq.android.spinkit.SpinKitView
android:id="#+id/spin_kit_job_board"
style="#style/SpinKitView.Large.WanderingCubes"
android:layout_width="#dimen/_80sdp"
android:layout_height="#dimen/_80sdp"
android:layout_gravity="center_horizontal|center_vertical"
app:SpinKit_Color="#color/color_white" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="#+id/extended_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:gravity="center"
style="#style/Widget.MaterialComponents.ExtendedFloatingActionButton.Icon"
android:onClick="expand"
app:iconSize="#dimen/_12sdp"
android:elevation="#dimen/_5sdp"
android:fontFamily="#font/roboto_light"
android:textColor="#color/white"
android:text="Filter"
app:iconPadding="#dimen/_5sdp"
android:layout_marginBottom="#dimen/_10sdp"
android:layout_marginRight="#dimen/_10sdp"
app:backgroundTint="#color/tutor_bear_dark_blue"
app:iconTint="#color/white"
app:icon="#drawable/ic_filter"
/>
<View
android:id="#+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_black_darker_overlay"
android:visibility="gone"
/>
<include layout="#layout/bottom_filter_dialog"
android:id="#+id/filterSheet"
android:visibility="gone"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I have a simple snack bar in my code like this.
Snackbar.make(binding.getRoot(), "This is main activity", Snackbar.LENGTH_LONG)
.setAction("CLOSE", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
}). show();
Problem is when I show the snack bar , it always appears above a certain height from the bottom of the screen. As if there is some kind of a bottom margin set. This only happens when I use coordinate layout.
Snackbar works fine in other layouts.
Picture of the problem is given as a reference.
Give the root view instead, rootLayout_job_board
CoordinatorLayout rootLayout = findViewById(R.id.rootLayout_job_board);
Snackbar.make(rootLayout), "This is main activity", Snackbar.LENGTH_LONG)
.setAction("CLOSE", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
}). show();
If that doesn't work, try giving GRAVITY using LayoutParams
If that doesn't work, also give margins as 0 in LayoutParams.
Also, if your device is Above 9 then you should consider navigation gestures,
snackbar.isGestureInsetBottomIgnored(false);
See here
I am trying to make a chat application. Where I have different layouts for receive messages and send messaged. I am not able to get smooth scroll maybe because of variable image size? I think this issue related to layout I have made for the chat message box.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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="wrap_content" xmlns:tools="http://schemas.android.com/tools"
android:layout_marginTop="11dp"
android:layout_marginRight="16dp"
android:gravity="right"
>
<android.support.v7.widget.AppCompatTextView
android:id="#+id/tv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="11dp"
android:paddingVertical="9dp"
android:visibility="gone"
tools:text="fdsfdsfsdfs"
tools:visibility="gone"
android:textColor="#2A2617"
android:textSize="15dp"
android:fontFamily="#font/nunito_regular"
/>
<android.support.v7.widget.AppCompatImageView
android:id="#+id/iv_message"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#+id/tv_message"
android:layout_width="200dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:padding="11dp"
android:visibility="gone" />
</RelativeLayout>
It flickers when i scroll up. Code of View Holder is as follow
when(data.messageType){
Constant.MessageType.TEXT ->{
messageIv.visibility = View.GONE
messageTv.apply {
visibility = View.VISIBLE
text = data.content
}
}
Constant.MessageType.IMAGE -> {
Glide.with(messageIv.context)
.load(data.content)
.apply(
RequestOptions()
.apply {
diskCacheStrategy(DiskCacheStrategy.ALL)
skipMemoryCache(true)
})
.into(messageIv)
messageIv.visibility = View.VISIBLE
messageTv.apply {
visibility = View.GONE
}
}
}
I guess it call bind every time i scroll and it makes the visibility gone and visible. Which cause the view to have 0dp size for some amount of time and suddenly when image loads, it creates a sudden scroll in the view making it very unstable.
Any work-around for this?
This is my xml:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefreshLayout"
android:layout_below="#id/id_bar"
android:layout_marginBottom="0.5dp"
android:background="#color/blue"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/list"
android:dividerHeight="0dp"
android:layout_gravity="top"
android:divider="#null"
android:background="#color/yellow"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.bartoszlipinski.recyclerviewheader2.RecyclerViewHeader
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="70dp"
android:visibility="gone"
android:layout_gravity="center_horizontal|top">
<include
android:id="#+id/header_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/rounded_top_green"
layout="#layout/header_profile"/>
</com.bartoszlipinski.recyclerviewheader2.RecyclerViewHeader>
<RelativeLayout
android:id="#+id/placeholderContainer"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:layout_height="match_parent">
<ImageView
android:id="#+id/placeholderPic"
android:layout_alignParentTop="true"
android:layout_marginTop="100dp"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/pin_newtrips"/>
<TextView
android:id="#+id/placeholderText"
android:layout_below="#id/placeholderPic"
android:padding="10dp"
android:textSize="28dp"
android:textColor="#color/gray32"
android:text="#string/home.status.heading.setup"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:id="#+id/placeholderAddItems"
android:layout_marginTop="10dp"
android:layout_below="#id/placeholderText"
android:layout_width="match_parent"
android:layout_height="wrap_content"></RelativeLayout>
</RelativeLayout>
</FrameLayout>
</android.support.v4.widget.SwipeRefreshLayout>
I initiate it via butterknife:
#InjectView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
This is my refreshListener:
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// Refresh items
if(timeLineAdapter!= null)
timeLineAdapter.setLastAnimatedPosition(0);
refresh(false);
}
});
I call this on onResume, so that it will work if I come back to it.
Now initially it works, if I press home button and come back, it works.
If I change my activity to another one, and then come back to it, it doesn't work anymore. How can this be fixed?
EDIT: As you can see, the main child of the SwipeRefreshLayout is a FrameLayout which contains the RecyclerView, my RecyclerViewHeader and a placeholder for the list (in here, cause swiping down on the placeholder should also swipe to refresh.
I Added between this 2 views, a ScrollView, and now the swipe to refresh works. BUT, having the recyclerview inside the scrollview ruins my recyclerView. I can scroll down but not up. Any other ideeas?
I had timelineList.setVisibility(View.Invisible) inside the code when I would check to see if I have objects to show inside the list.
I removed that and set this instead:
if(timeLineAdapter != null) {
timeLineAdapter.clearItems();
timeLineAdapter.notifyDataSetChanged();
}
Now the list is not set as invisible nowhere.
I added my placeholder and list inside the SwipeRefreshLayout, thinking that it will work on both, but in reality it only works on the list, so if the list is gone, the pull to refresh is gone
Do you know how to set a background image when the recycler view is empty? Like Gmail app...
Question 2: is there a repository where I can find official images by Google for this purpose?
EXAMPLE
Yes, there is an official, Google maintained Github repository. Contains the latest version of their material icons, which are used on all Google apps.
Google's Material Design Icons Repository
And, regarding your first question: yes.
You can check if the adapter you are using to populate your RecyclerView is empty (or/and if the adapter has no items). If true, show the image, else, deal with the RecyclerView. Like this:
if (mAdapter.getItemCount() == 0) {
// show my background image
// do stuff
} else {
// RecyclerView stuff
}
To elaborate a bit on #herrmartell answer and to manage streched drawables as background: This solution switches the howl recView for another linearlayout having the same effect as you request but looks in my case prettier after trying lots of different possibilities. If you change your list you have to call the handler function abviously again.
Your Fragment that handles the RecyclerView:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
//...
//setup recView like -> recView = view.findViewById(R.id.yourListRecyclerView);
//adapter setup
//set to recView
handleRecyclerViewState(view);
}
private void handleRecyclerViewState(View view) {
View emptyView = view.findViewById(R.id.empty_view);
if (adapter.getItemCount() == 0) {
recView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
} else {
recView.setVisibility(View.VISIBLE);
emptyView.setVisibility(View.GONE);
}
}
Inside your RecView layout xml:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/yourListRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingBottom="80dp"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<include
android:id="#+id/empty_view"
android:layout_gravity="center_horizontal|bottom"
layout="#layout/empty_view"
android:layout_height="match_parent"
android:layout_width="match_parent">
</include>
Exact layouting and design might differ for sure.
Here the Layout of the empty_view.xml that shows a drawable svg image and a message underneath:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<ImageView
android:id="#+id/empty_image"
android:layout_width="220dp"
android:layout_height="250dp"
android:src="#drawable/ic_no_files" />
<TextView
android:id="#+id/emptyMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Nothing here!"
android:alpha="0.3"
android:textColor="?android:attr/textColor" />