Prevent Android Activity from Operating while using Bottom Sheet in PSLab App

This blog demonstrates how to prevent the Android Activity in the background from operating while the Bottom Sheet is up in the foreground. The demonstration will be purely from the work I have done under PR #1355 in PSLab Android repository. Why prevent the Activity from operating? When using Bottom Sheet in Android, it is preferable to dim the screen behind the Bottom Sheet to provide a good user experience. But the dimming of the screen is itself an indication that the screen won’t work. Also, if the Bottom Sheet is open and while sliding it, if, by mistake, any button in the background of the bottom sheet gets pressed, then if the function related to that button starts executing then it can create a bad user experience. For example, in PSLab Android app, in Accelerometer instrument, there are record/pause and delete buttons in the toolbar as shown in figure 1. Now, if the bottom sheet is opened and while closing it if the delete button is by mistake pressed by the user, then whole recorded data gets deleted. Thus, it’s a good practice to prevent the background Activity from operating while Bottom Sheet is opened. Figure 1. Accelerometer Instrument in PSLab Android app How to prevent the Activity from operating? In this demonstration, I will use the method followed by PSLab Android app in creating a Bottom Sheet and making the background dim using a View widget. A step by step guide on how to make a Bottom Sheet as in PSLab Android app can be found in [1] and [2]. Strategy The strategy used in solving this problem is setting an OnClickListener to the View that is used to dim the background and close the Bottom Sheet (if open) and hide the View as soon as the method is called. The View is again made visible when an upward slide gesture is made to open the Bottom Sheet. Follow the below steps to get the desired results: First, in OnCreate() method, set the OnTouchListener to the view. view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED) bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); tvShadow.setVisibility(View.GONE); } }); Now, override the OnSlide() method of the GestureDetector class and add the following code to it. @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { Float value = (float) MathUtils.map((double) slideOffset, 0.0, 1.0, 0.0, 0.8); view.setVisibility(View.VISIBLE); view.setAlpha(value); } So, now test the Bottom Sheet and you will find that the Bottom Sheet will get closed as soon as the click is made outside it if it is opened. The demonstration of the working of the above code is shown in figure 2. Figure 2. Demonstration of preventing the background Activity from operating while Bottom Sheet is up Resources http://thetechnocafe.com/make-bottom-sheet-android/: Blog on how to make a Bottom Sheet in Android

Continue ReadingPrevent Android Activity from Operating while using Bottom Sheet in PSLab App

Making Bottomsheet responsive using Custom Gesture Detector in PSLab Android App

In the previous blog Creating Instruction Guide using Bottomsheet, I have created the Bottom Sheet guide in instrument activities in PSLab Android app. But simply adding the Bottom Sheet in the layout is not enough as it could lead to some UI issues like no proper way to show or hide the Bottom Sheet, therefore, he/she will find it difficult to work with Bottom Sheet that could degrade User Experience. We need to make the Bottom Sheet responsive and interactive which we can do by capturing swipe gestures done by the user and overriding their functionality i.e. when the user slides up with the finger then the Bottom Sheet will reveal itself and when the user slides the finger down the Bottom Sheet will hide. For this Android provides a class GestureDetector which is used with another class SimpleOnGestureListener which acts as a listener to capture Gesture events like swipe, pinch, scroll, long press etc. In this blog, I will create a custom gesture listener that will listen to the swipe events and according to the gestures it will show/hide the Bottom Sheet. I will start by creating a gesture listener class called “SwipeGestureListener” extending the class ‘GestureDetector.SimpleOnGestureListener’ and also as I need swipe gestures to control the Bottom Sheet, so I will pass the reference of the Bottom Sheet as a parameter in the constructor. public class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener{ private BottomSheetBehavior bottomSheet; public SwipeGestureDetector(BottomSheetBehavior bt) { bottomSheet = bt; } } Now in this listener class as we are concerned with the swipe events so will only override the below method provided by ‘GestureDetector.SimpleOnGestureListener’ interface public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) This method is called whenever the user swipes its finger in any direction. In the above code, we can see that the method provides with object e1 and e2 of type MotionEvent. The MotionEvent class is used to report movements in terms of Action Codes like ACTION_DOWN, ACTION_UP and also contains other information about the touch like the pressure of the touch, x and y coordinate, orientation of the contact area etc.  The e1 object will have the attribute values relating to the point when the swipe started and the e2 object will have attribute values relating to the point when the swipe has ended. Now, the main thing we need to determine if the direction of the swipe which is not directly available using the MotionEvent object. So, to determine the direction of the swipe I will fetch the coordinates of the initial point and terminal point of the swipe using the objects initial and final point i.e., e1 and e2. //Initial Point float x1 = e1.getX(), y1 = e1.getY(); //Final Point float x2 = e2.getX(), y2 = e2.getY(); Then, using these coordinates to calculate the angle of the swipe and based on the angle I will return the direction of the swipe as shown in the code below private Direction getDirection(float x1, float y1, float x2, float y2) { Double angle = Math.toDegrees(Math.atan2(y1 - y2,…

Continue ReadingMaking Bottomsheet responsive using Custom Gesture Detector in PSLab Android App

Creating Instruction Guide using Bottomsheet

The PSLab android app consists of different instruments like oscilloscope, multimeter, wave generator etc and each instrument has different functionality and usage so it is necessary that there should be an instruction guide for every instrument so that the user can easily read the instruction to understand the functionality of the instrument. In this we will create an instruction guide for the Wave Generator which will contain information about the instrument, it’s functionalities, steps for how to use the instrument. The main component that I used to create instruction guide is Bottom Sheet. Bottom Sheet is introduced in Android Support v23.2 . It is a special UI widget which slide up from the bottom of the screen and it can be used to reveal some extra information that we cannot show on the main layout like bottom menus,  instructions etc. They are of two types : Modal Bottom Sheet:-  This Bottom Sheet has properties very similar to normal dialogs present in Android like elevation only difference is that they pop up from the bottom of screen with proper animation and they are implemented using BottomSheetDialogFragment Class. Persistent Bottom Sheet:- This Bottom Sheet is included as a part of the layout and they can be slid up and down to reveal extra information. They are implemented using BottomSheetBehaviour Class. For my project, I used persistent Bottom Sheet as modal Bottom Sheet can’t be slid up and down by the swipe of the finger whereas persistent Bottom Sheet can be slid up and down and can be hidden by swipe features. Implementing the Bottom Sheet Step 1: Adding the Dependency To start using Bottom Sheet we have to add the dependency (We have also include Jake Wharton-Butterknife library for view binding but it is optional.) dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "com.android.support:appcompat-v7:26.0.1" implementation "com.android.support:design:26.0.1" implementation "com.jakewharton:butterknife:8.8.1" annotationProcessor "com.jakewharton:butterknife-compiler:8.8.1" Step 2: Creating Bottom Sheet layout file In this step, we will create the layout of the Bottom Sheet, as our purpose of making Bottom Sheet is to show extra information regarding the instrument so we will include ImageView and TextView inside the layout that will be used to show the content later. Some attributes in the layout worth noting are: app:layout_behavior: This attribute makes the layout act as Bottom Sheet. app:behavior_peekHeight: This is the height of the Bottom Sheet when it is minimized. app:behavior_hideable: Defines if the Bottom Sheet can be hidden by swiping it down. Here, we will also create one extra LinearLayout having height equal to the peek_height. This  LinearLayout will be at the top of the BottomSheet as shown in Figure 1 and it will be visible when the BottomSheet is in a minimized state(not hidden). Here we will put text view with like “Show guide” and an arrow pointing upwards so that it is easier for the user to understand that sheet can be viewed by sliding up. Here is the gist[2] that contains code for the layout of the Bottom Sheet guide After this step, we can see a layout…

Continue ReadingCreating Instruction Guide using Bottomsheet

Implementing Attendee Detail BottomSheet UI in Open Event Orga App

In Open Event Orga App (Github Repo), we allow the option to check the attendee details before checking him/her in or out. Originally, a dialog was shown showing the attendee details, which did not contain much information about the attendee, ticket or the order. The disadvantage of such design was also that it was tied to only one view. We couldn’t show the check in dialog elsewhere in the app, like during QR scanning. So we had to switch back to the attendee view for showing the check in dialog. We decided to create a usable detached component in the form of a bottom sheet containing all required information. This blog will outline the procedure we employed to design the bottom sheet UI. The attendee check in dialog looked like this: So, first we decide what we need to show on the check in bottom sheet: Attendee Name Attendee Email Attendee Check In Status Order Status ( Completed, Pending, etc ) TIcket Type ( Free, Paid, Donation ) Ticket Price Order Date Invoice Number Order ‘Paid Via’ As we are using Android Data Binding in our layout, we’ll start by including the variables required in the layout. Besides the obvious attendee variable, we need presenter instance to handle the check in and check out of the attendee and DateUtils class to parse the order date. Additionally, to handle the visibility of views, we need to include the View class too <data> <import type="org.fossasia.openevent.app.utils.DateUtils" /> <import type="android.view.View" /> <variable name="presenter" type="org.fossasia.openevent.app.event.checkin.contract.IAttendeeCheckInPresenter" /> <variable name="checkinAttendee" type="org.fossasia.openevent.app.data.models.Attendee" /> </data>   Then, we make the root layout to be CoordinatorLayout and add a NestedScrollView inside it, which contains a vertical linear layout in it. This vertical linear layout will contain our fields. Note: For brevity, I’ll skip most of the layout attributes from the blog and only show the ones that correspond to the text Firstly, we show the attendee name: <TextView style="@style/TextAppearance.AppCompat.Headline" android:text='@{attendee.firstName + " " + attendee.lastName }' tools:text="Name" />   The perks of using data binding can be seen here, as we are using string concatenation in layout itself. Furthermore, data binding also handles null checks for us if we add a question mark at the end of the variable name ( attendee.firstName? ). But our server ensures that both these fields are not null, so we skip that part. Next up, we display the attendee email <TextView android:text="@{ checkinAttendee.email }" tools:text="xyz@example.com" />   And then the check in status of the attendee <TextView android:text="@{ checkinAttendee.checkedIn ? @string/checked_in : @string/checked_out }" android:textColor="@{ checkinAttendee.checkedIn ? @color/light_green_500 : @color/red_500 }" tools:text="CHECKED IN" />   Notice that we dynamically change the color and text based on the check in status of the attendee Now we begin showing the fields with icons to their left. You can use Compound Drawable to achieve this effect, but we use vector drawables which are incompatible with compound drawables on older versions of Android, so we use a horizontal LinearLayout instead. The first field is the order status denoting…

Continue ReadingImplementing Attendee Detail BottomSheet UI in Open Event Orga App