Hiding Multiple Attendee Recycler for Single Tickets in Open Event Android

Multiple attendee recycler allows the user to easily write in attendee details for all tickets he/she is buying. The UI for attendee details fragment can be divided into two segments, one contains the details of the person creating the whole order and followed by multiple details section for the attendee of every ticket. This is a good way to take details when multiple ticket or tickets with greater than 1 quantity is involved. However, if there is only one attendee detail to be taken instead of asking the user for order creator’s details and then first attendee details it is better to add some views in the creator segment and not ask for the same details again from the user. This blog post will help you in understanding how it's done in Open Event Android. Keeping a track of orders with single attendee We keep a boolean to track whether or not the sum of quantities of tickets selected by a user is one since one attendee is to be generated per ticket quantity. And incase it is boolean variable singleTicket is set to True which is false by default initially. Following is how it can be done singleTicket = ticketIdAndQty?.map { it.second }?.sum() == 1 The above statements basically iterate over the list of pairs of tickets and their quantity and then sums over the second element of all pairs that is the quantities, if the summation leads to 1 single ticket is set to True else false. Adding elements to recycler adapter The next step is to update the logic as to when blank attendees are added to recycler adapter. The idea is to check the boolean singleTicket and if it is false dont insert any attendee. attendeeFragmentViewModel.tickets.observe(this, Observer {                it?.let {                    if (!singleTicket)                        it.forEach {                            val pos = ticketIdAndQty?.map { it.first }?.indexOf(it.id)                            val iterations = pos?.let { it1 -> ticketIdAndQty?.get(it1)?.second } ?: 0                            for (i in 0 until iterations)                                attendeeRecyclerAdapter.add(Attendee(attendeeFragmentViewModel.getId()), it)                            attendeeRecyclerAdapter.notifyDataSetChanged()                        }                }            }) If a single ticket is false regular procedure to add blank attendee is carried out. The quantity of ticket is found and the same quantity of attendees are added to recycler adapter’s attendee's list similary ticket information is also added to the recycler adapter. The id for blank attendees is taken from the attendeeViewModel’s getId function which in turn simply returns id using the authHolder’s getId function. Modify the register method to check for the single attendee So far what we have discussed helps us display the right no of details section on the UI. We will also have to modify the register method to take into account the above changes. Following is the implementation of what happens when the user selects register. rootView.register.setOnClickListener {                if (selectedPaymentOption == "Stripe")                    sendToken()                val attendees = ArrayList<Attendee>()                if (singleTicket) {                    val pos = ticketIdAndQty?.map { it.second }?.indexOf(1)                    val ticket = pos?.let { it1 -> ticketIdAndQty?.get(it1)?.first?.toLong() } ?: -1                    val attendee = Attendee(id = attendeeFragmentViewModel.getId(),                            firstname = firstName.text.toString(),                            lastname = lastName.text.toString(),                            city = getAttendeeField("city"),                            address =…

Continue ReadingHiding Multiple Attendee Recycler for Single Tickets in Open Event Android

Implementing Card View in PSLab app

Card View was announced by Google in I/O ‘14 conference. Although it started a bit slow, but now we can see most of the apps like Snapchat, Google, Facebook, etc. using this widget. So, this blog is solely contributed on how to implement Card View in your own app by taking example of PSLab application. What is Card View ? CardView is a view container or ViewGroup that inherits its nature from FrameLayout which further inherits from ViewGroup itself. The only thing that separates a CardView from any other ViewGroups is its nature to behave like a card, more specifically the shadow and rounded corners. The basic customization that a CardView provides includes CornerRadius, Elevation, MaxElevation, ContentPadding, CompatPadding, PreventCornerOverlap, and a dedicated CardBackgroundColor or say Card Background which is the most necessary feature for a card to look cool. Step by Step description how CardView was implemented in PSLab First step is to add dependencies in your project as widgets like Card View, Recyclerview, etc. are not included in a common repository of widgets provided by Google. App level dependency : compile 'com.android.support:cardview-v7:26.0.0' compile 'com.android.support:recyclerview-v7:+' If you are using Android Studio 3.0+ than add the following dependency instead of above : implementation 'com.android.support:cardview-v7:26.0.0' implementation 'com.android.support:recyclerview-v7:27.1.1'  Now we can use Card View widget in our app. So, first make add card view in layout section like this : <android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="@dimen/total_height_card" android:layout_gravity="center" android:layout_margin="@dimen/card_margin" card_view:cardCornerRadius="@dimen/card_radius"> </android.support.v7.widget.CardView> These are the basic attributes that are used while declaring a card view. Other possible attributes can be : Elevation - Used to elevate card to give a depth effect MaxElevation - Used to give constraint to the depth effect ContentPadding - Used to provide padding between content and the card PreventCornerOverlap - To prevent different corners to overlap as shown in figure 1. Figure 1. Image showing corner overlapping in CardView Now to set the objects inside the Card View, mostly RelativeLayout is preferred as it gives the freedom to place objects in reference of others whereas LinearLayout provides freedom to place them in only one direction. Other layouts such as FrameLayout, Tables, etc. can be used as per the need of the app. Now we will create a layout that will hold all the cards using RecyclerView. <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"/> Now after setting the layouts, it's time to make adapter which inflates the information in the cards which is then represented using RecyclerView. public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.Holder> { private List<ApplicationItem> applicationList; private final OnItemClickListener listener; /** * View holder for application list item */ public class Holder extends RecyclerView.ViewHolder { TextView header, description; ImageView applicationIcon; //Background Image public Holder(View itemView) { super(itemView); this.header = itemView.findViewById(R.id.heading_card); this.description = itemView.findViewById(R.id.description_card); this.applicationIcon = itemView.findViewById(R.id.application_icon); } public void setup(final ApplicationItem applicationItem, final OnItemClickListener listener) { header.setText(applicationItem.getApplicationName()); description.setText(applicationItem.getApplicationDescription()); applicationIcon.setImageResource(applicationItem.getApplicationIcon()); } } public ApplicationAdapter(Context mContext, List<ApplicationItem> applicationList, OnItemClickListener listener) { this.mContext = mContext; this.applicationList = applicationList; this.listener = listener; } @Override public Holder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.application_list_item, parent, false); return…

Continue ReadingImplementing Card View in PSLab app

Datewise splitting of the Bookmarks in the Homescreen of Open Event Android

In the Open Event Android app we had already incorporated bookmarks in the homescreen along with an improved UI. Now there was scope for further improvement in terms of user experience. The bookmarks were already sorted date wise but we needed to place them under separate date headers. In this blog I will be talking about how this was done in the app.                 Initially the user had no way of knowing which session belonged to which day. This could be fixed with a simple addition of a header indicating the day each bookmark belonged to. One way to do this was to add a day header and then get the bookmarks for each day and so on. But this proved to be difficult owing to the fact the number of days could be dynamic owing to the fact that this is a generic app. Another issue was that adding change listeners for the realm results to the bookmarks list for each day produced view duplication and other unexpected results whenever the bookmark list changed. So another approach was chosen that was to get all the bookmarks first and then add the date header and traverse through the bookmarks and only add sessions which belong to the date for which the date header was added earlier. Bookmark Item Support in GlobalSearchAdapter The main reason why we are reusing the GlobalSearchAdapter is that we have already defined a DIVIDER type in this adapter which can be reused as the date header. We needed to initialize a constant for the Bookmark type. private final int BOOKMARK = 5; //Can be any number Then we add the Bookmark type in the getItemViewType() function which would return a constant that we defined earlier to indicate that in the filteredResultList we have an object of type Bookmark. @Override public int getItemViewType(int position) {    if (filteredResultList.get(position) instanceof Track) {        return TRACK;    }     //Other Cases here    } else if(filteredResultList.get(position) instanceof Session){        return BOOKMARK;    } else {        return 1;    } } Now we create the viewholder if the list item is of the type Session which in this case will be a bookmark. @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {    RecyclerView.ViewHolder resultHolder = null;    LayoutInflater inflater = LayoutInflater.from(parent.getContext());    //Other cases for Track,Location etc case BOOKMARK:    View bookmark = inflater.inflate(R.layout.item_schedule, parent, false);    resultHolder = new DayScheduleViewHolder(bookmark,context);    break;   //Some code } Now we do the same in onBindViewHolder(). We bind the contents of the object to the ViewHolder here by calling the bindSession() function. We also pass in an argument which is our database repository i.e realmRepo here. @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {     switch (holder.getItemViewType()) {     //Other cases handled here case BOOKMARK:    DayScheduleViewHolder bookmarkTypeViewHolder = (DayScheduleViewHolder) holder;    Session bookmarkItem = (Session) getItem(position);    bookmarkTypeViewHolder.setSession(bookmarkItem);    bookmarkTypeViewHolder.bindSession(realmRepo);    break; } Updating the AboutFragment private GlobalSearchAdapter bookMarksListAdapter; private List<Object> mSessions =…

Continue ReadingDatewise splitting of the Bookmarks in the Homescreen of Open Event Android