Menu item inside NavigationView onClick is triggered only on double click - android

I've created menu for NavigationView by adding ListView inside my NavigationView. Then I made custom ArrayAdapter where each menu item is added. Each menu item has custom xml layout attached to it. Root of this layout is used by onClickListener triggering function passed to menu item class as parameter.
Everything works perfectly, but as I click on item, it will not trigger this function, only as I double click. Why is this behavior happening?
Code:
This is class for menu item (multiple different items are extending this class)
Not every menu item has click event (for example section headers)
abstract class DrawerItem(var itemName: String, var imgResID: Int, var onClick: (() -> Unit)? = null)
This is how onClick is called inside getView function for some menu items:
val root: LinearLayout = view.findViewById(R.id.root)
root.setOnClickListener {
menuItem.onClick?.invoke()
}
XML layout for NavigationView:
<com.google.android.material.navigation.NavigationView
android:id="#+id/drawer_menu"
android:layout_gravity="left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#color/white">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/navigation_header_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
<ListView
android:id="#+id/lst_menu_items"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</com.google.android.material.navigation.NavigationView>
Layout of one menu item type:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/root"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:background="#drawable/navig_menu_selector"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:duplicateParentState="true"
android:clickable="false"
android:padding="#dimen/padding_medium">
<ImageView
android:id="#+id/navig_ico"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center_vertical"/>
<TextView
android:id="#+id/navig_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="#dimen/padding_medium"
style="#style/navig_item_text"/>
</LinearLayout>
<include layout="#layout/custom_separator"/>
</LinearLayout>

Clear the app's cache or delete it altogether and try downloading it again. I don't know the cause, but I solved the problem.

Related

SwipeRefreshLayout does not work anymore, if I change activity, and then come back

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

How can I have one unique button in multiple components of a layout in android?

So I have an xml that consists of a linear layout containing a Button and a TextView like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical">
<Button
android:id="#+id/btnCell"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingLeft="40dp"
android:text="Button"
android:textColor="#color/blueText" />
<View
android:height="wrap_content"
android:width="wrap_content"
android:background="#drawable/Test"/>
</LinearLayout>
And I want to use this same layout inside other layouts in a different xml. I need the same button at every time, so I reuse it by including it in the two layouts (both layouts are in the same xml, but ones is hidden):
First one
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/image"
/>
<include layout="#layout/buttonLayout"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Second One:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/image"
/>
<include layout="#layout/buttonLayout"/>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
So I show the first layout and hide the second one at the beginning of the app , as the user moves within the interface, the layouts exchange so that the other one is shown and the first one hidden.
The thing is that I declare the Button in my java activity class like this:
btnCell = (Button) thirdView.findViewById(R.id.btnCell);
btnCell.setOnClickListener(this);
And implemented the listener.
#Override
public void onClick(View v) {
if (v == btnCell) {
System.out.println("entered if");
}
System.out.println("entered function");
}
The problem is that when I click the button when the first view is shown and the second hidden, the button works just fine, but when I unhide the second layout, hide the first one, and proceed to click the button, that should be the same as the first one but in a different layout, nothing happens. I searched and find out, that this happens because the id is assigned only to the button shown in the first layout because of view hierarchy, but not the one in the second layout. How can I make both buttons react to the same action, without declaring a new button in each layout but instead reusing it?
I have used this type of layout. you can create Id different for both and inflate that view and give different name so You can differentiate both thing.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/image"
/>
<include android:id="+id/firstOne" layout="#layout/buttonLayout"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
android second one is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/image"
/>
<include android:id="+id/secondTwo" layout="#layout/buttonLayout"/>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
The Problem is both the layout are include in same layout file and the id of that
button are same so whenever you click on any of the button at the same time event will fire on both button like both are clicked.
So, you have to give the different id for both the button I hope it works fine..
You can add a different Id for each included layout:
<include android:id="+id/layout_a" layout="#layout/buttonLayout"/>
and
<include android:id="+id/layout_b" layout="#layout/buttonLayout"/>
and then use two findViewById to reach them:
btnCellA = (Button)thirdView.findViewById(R.id.layout_a).findViewById(R.id.btnCell);
btnCellB = (Button)thirdView.findViewById(R.id.layout_b).findViewById(R.id.btnCell);

How to make the last footer fixed (ListView)

I have a ListView with 2 footer views. The first one is a bunch of TextViews, while the second one is a button. I'm trying to fix the second footer so that it always shows at the bottom of the screen.
I tried the following:
1. alignParentBottom = true
2. layout_gravity="bottom"
3. footerView2.bringToFront()
And combinations of the above. But none of them worked out. How can I achieve this?
UPDATE
I shouldn't have added the View which I always want on the screen (fixed) as footer.
I just added the wannabe-fixed-view with the listView. Did alignParentBottom = true and also view.bringToFront(). It worked out for me.
Separate your ListView and bottom footer. The idea is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btn_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Bottom button"/>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/btn_bottom"/>
</RelativeLayout>
Create separate xml file which contain all textviews and button you want as footer part.Then bind this xml as a footer of listview. You can binf footer with listview by this method: listview.addFooterView(footerView);
For example:
View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.listviewfooter, null, false);
spDate = (Spinner) headerView.findViewById(R.id.spdate);
llDatepicker = (LinearLayout) headerView.findViewById(R.id.lldatepicker);
rvDatepicker = (RecyclerView) headerView.findViewById(R.id.rvdatepicker);
rvTimepicker = (RecyclerView) headerView.findViewById(R.id.rvtimepicker);
lvAddress.addFooterView(footerView);
If you are Trying to add a View which will be shown even if we scroll the List Up or Down... u can do something like this. I had done this before But as a header.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/new_container"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="LOAD EARLIER MESSAGES"
android:id="#+id/loadMore"
android:background="#90F58220"
android:visibility="visible"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/listContainer"
android:layout_below="#+id/loadMore"
android:layout_above="#+id/container">
<ListView
android:id="#+id/messagesContainer"
android:transcriptMode="normal"
android:dividerHeight="0dp"
android:divider="#null"
android:stackFromBottom="true"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/container"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:background="#ffffff"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:layout_height="wrap_content" >
</RelativeLayout>
The LoadMore Button is always visible on the Top of the List...
To add it to footer, Just Change
android:layout_below="#+id/loadMore"
android:layout_above="#+id/container"
to
android:layout_above="#+id/loadMore"

RecyclerView empty after SwipeRefreshLayout pull onRefresh event

I'm trying to implement a Swipe down Refresh Widget for a RecyclerView but am receiving some strange behavior. Here is what the working recyclerView with cardViews looks like. I've included the XML view definition below:
The issue:
After refreshing, the RecyclerView (recycler_view) which resides inside the SwipeRefreshLayout view (swipe_refresh_main) does not populate with any cardViews:
The cardViews only become visible after I scroll down past the third, invisible item. I believe this is because of how the RecyclerAdapter works, loading and unloading views depending on their screen visibility. This makes sense in my case because only when the fourth item becomes partially visible, do the previous cardViews also appear.
I examined the view hierarchy before and after and it is evident that the layouts containing the cardViews aren't present after refreshing:
Layout pre-refresh:(notice the three layouts containing visible cardViews)
Layout post-refresh:(notice the empty recyclerView)
I know this has something to do with how the refresh listener responds to the swipe refresh action, but I can't figure out why it isn't redisplaying the view prior to refresh.
Refresh Listener calls this method:
#Override
public void showWordList(ArrayList<Word> wordArrayList){
if(mWordRecyclerAdapter == null){
mUnfilteredDataSet = wordArrayList;
mWordRecyclerAdapter = new WordRecyclerAdapter(wordArrayList, this, this);
mWordRecyclerAdapter.getFilter().filter(dataSetMode);
recyclerView.setAdapter(mWordRecyclerAdapter);
}else{
mWordRecyclerAdapter.getFilter().filter(dataSetMode);
recyclerView.setAdapter(mWordRecyclerAdapter);
}
}
The filter method inside of my recyclerAdapter rebuilds the arrayList dataset based on which menu item is selected. In this case, for the refresh, the arrayList remains unchanged:
getFilter method:
#Override
public Filter getFilter() {
Filter filter = new Filter(){
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mWordArrayList = (ArrayList<Word>)results.values;
notifyDataSetChanged();
}
I started to suspect that the notifyDataSetChanged method might have some something to do with this, but I'm not sure. I'm now leaning towards some sort of band-aid fix, such as a method that will force the view to scroll or to reload. Any suggestions would be helpful. Thanks!
XML Layout:
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
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">
<!--Main activity UI-->
<RelativeLayout
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:context=".HomeActivity"
android:background="#color/material_grey_100">
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
android:background="#color/primary_material_light"
android:elevation="4dp"
android:theme="#style/Base.ThemeOverlay.AppCompat.Light"
>
<AutoCompleteTextView
android:id="#+id/search_box"
android:singleLine="true"
android:gravity="center_vertical|left"
android:layout_width="300dp"
android:popupBackground="#ffff"
android:layout_height="wrap_content"
android:dropDownWidth="wrap_content"
android:background="#android:color/transparent"
android:visibility="gone"
android:hint="Español o Inglés"
android:completionThreshold="2"
/>
<ImageView
android:id="#+id/search_query_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:paddingLeft="16dp"
android:paddingRight="4dp"
android:src="#drawable/ic_magnify_grey600_24dp"
/>
<ImageView
android:id="#+id/search_clear_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:visibility="invisible"
android:src="#drawable/ic_close_grey600_36dp"
/>
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="wrap_content"
android:layout_below="#id/toolbar"
android:layout_height="wrap_content"
android:background="#color/cardview_dark_background"
android:id="#+id/swipe_refresh_main">
<!--Main CardView holder-->
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:scrollbars="vertical"/>
</android.support.v4.widget.SwipeRefreshLayout>
<!--Nav Fragments container-->
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/toolbar"/>
</RelativeLayout>
<!--Drawer Nav UI-->
<android.support.design.widget.NavigationView
android:id="#+id/nav_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:divider="#android:color/transparent"
android:background="#android:color/white"
app:menu="#menu/drawer_view"
app:headerLayout="#layout/nav_header"/>
</android.support.v4.widget.DrawerLayout>

SearchView suggestions are showing over the widget

I'm using the searchview at the top of my activity positioned just below the action bar, the problem is that the suggestions are displayed over the searchview so the user cant see the typed the text
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v7.widget.SearchView
android:id="#+id/fragment_map.searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.SearchView>
<RelativeLayout
android:layout_below="#id/fragment_map.searchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/map_container">
<!-- The map fragments will go here -->
</RelativeLayout>
</RelativeLayout>
no clue what the official answer even means. a work colleague aided me and I wanted to show how this can be achieved:
it can be done programatically by getting the textview as an AutoCompleteTextview:
imagine you have a searchview in xml like this:
<android.support.v7.widget.SearchView
android:id="#+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="10dp"
android:animateLayoutChanges="true"
android:paddingLeft="0dp"
app:closeIcon="#drawable/close_x_icon"
app:queryBackground="#drawable/search_bg_expanded"
app:searchHintIcon="#drawable/empty_drawable"
app:searchIcon="#null" />
then in code do this:
val searchText = searchView.findViewById<TextView>(android.support.v7.appcompat.R.id.search_src_text) as? AutoCompleteTextView
searchText?.dropDownAnchor = searchView.id
so once you cast it to an AutocompleteTextView you can change the anchor basically.
fixed by adding this view to the bottom of the relativelayout and setting it to the anchor
<View android:id="#+id/fragment_map.dropDownAnchor"
android:layout_below="#id/fragment_map.searchView"
android:layout_width="match_parent"
android:layout_height="0dp" />

Categories

Resources