Basically I have a drawer with a button in it. When I click on the button I want to hide a view (another button) that is loaded in the FrameLayout.
Below I include the XML code for the drawer. The button is not included there because it is generated dynamically within the code.
I tried getting the frameLayout and invalidating the view, but it does not seem to work. I think it is somehow related to the fact that it is loaded in a Fragment.
Any clue is more than welcome! Thanks!
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myDrawer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/home_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="#layout/home_layout" />
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
Alright, got it working. I thought there was some hidden magic related to the fact of using FrameLayout, but not. The method is completely the same. Find the solution below:
View view;
if ((view = findViewById(R.id.bottomSet)) != null) {
view.setVisibility(View.VISIBLE);
view.invalidate();
}
Note that "bottomSet" is defined within the FrameLayout that is being imported.
Related
I'm seeing this strange behavior and couldn't find anything similar to this.
So I have a parent Activity and inside is a Fragment, which I'm including in parent via include element and then in parent's onCreate, create Fragment and replace it with this include layout (Tell me if this is a right way? I was using FrameLayout but then switched to include and defined an id to it).
Activity
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.sourcey.materiallogindemo.CustomerDetailActivity"
tools:ignore="MergeRootFrame">
<com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.appbar.MaterialToolbar />
</com.google.android.material.appbar.AppBarLayout>
<include
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/app_bar"
app:layout_constraintBottom_toTopOf="#id/layout_bottom_bar"
layout="#layout/fragment_customer_detail" />
<androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.bottomappbar.BottomAppBar>
</com.google.android.material.bottomappbar.BottomAppBar>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.sourcey.materiallogindemo.CustomerDetailFragment"
android:layout_height="match_parent"
android:layout_width="match_parent">
<!-- THIS IS THE CULPRIT -->
<com.google.android.material.button.MaterialButton
android:id="#+id/btn_update_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.google.android.material.button.MaterialButton />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/sku_list"
app:layoutManager="LinearLayoutManager"
tools:context="com.sourcey.materiallogindemo.CustomerDetailFragment"
tools:listitem="#layout/fragment_s_k_u_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment is inflated correctly but when I do this inside onCreateView
rootView.btn_update_position.setOnClickListener {
// ... log something
}
and press the Button, it doesn't do anything? Even though most findings were led to this suggestion that I should inflate the view and then set onClickListener.
I also tried doing these
rootView.findViewById<MaterialButton>(R.id.btn_update_position).setOnClickListener {
// ... log something
}
and
val button = rootView.findViewById<MaterialButton>(R.id.btn_update_position)
button.setOnClickListener {
// ... log something
}
but none of them works.
I also tried above approaches in onViewCreated to see if maybe I was not getting the reference but no errors were thrown and no reaction was coming.
Only thing that works is this
activity?.findViewById<MaterialButton>(R.id.btn_update_position)
?.setOnClickListener {
// ... log something
}
I'm trying to understand why this happens? Could this be the issue of using include the Fragment?
NOTE I'm not a pro in android just do hobby work in it so don't know very deeply about it.
EDIT As you can see I have a RecyclerView in Fragment layout, I'm inflating the layout and then setting its adapter items which seems to work fine opposed to button.
rootView.sku_list.adapter = Adapter()
I'm bit confused about what you want to do here
First,<include> doesn't create new view, it just include the xml into the parent xml file so basically it still on activity and you need activity to findViewById
Second, about your question what different between FrameLayout and <include>.
With <include> like i said above, it just add xml file to the parent file, the main usage is for re-use layout (you can include it anywhere) .
With FrameLayout, from official doc : "FrameLayout is designed to block out an area on the screen to display a single item". E.g : you want your layout have a header and footer for all screen, only the middle part change so place a frame layout at middle then load different view for each screen, because that flexibility frame layout usually use for display fragment (you can google how to use frame layout for more details)
I am extending a "MapView" that itself extends FrameLayout. But I can't access the ui elements I added: level_layout and *level_scroll. I have no trouble adding the code directly to my MainActivity, but I can't get it to work in a library.
<?xml version="1.0" encoding="utf-8"?>
<android.company.com.library.mapbox.MyMapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mapView">
<ScrollView
android:id="#+id/level_scroll"
android:layout_width="50dp"
android:layout_height="250dp"
android:layout_gravity="right"
android:layout_marginTop="100dp"
android:orientation="vertical">
<LinearLayout
android:id="#+id/level_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"></LinearLayout>
</ScrollView>
</android.company.com.library.mapbox.MyMapView>
In MyMapView.java I am getting a value from:
int level = R.id.level_layout;
But linear is null when trying to get the LinearLayout
LinearLayout linear = (LinearLayout) findViewById(R.id.level_layout);
I tried Adding
#Override
protected void onFinishInflate() {
super.onFinishInflate();
}
(I try to access my ui elements after this is called)
Calling the following in different places (e.g. constructors)
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.nameOfTheXmlFile, null);
I don't have multiple layout files with the same name.
I can't use setContentView(...) since this is a View and not an Activity?
Official documentation to MapView here explicitly says
Note: You are advised not to add children to this view.
This means that MapView custom inner views are supported only partially, or not supported at all. I would not recommend you to use something that is badly supported since it may produce weird bugs as the one you have. Especially in MapView with its complicated touch listener and extensive inner UI - you can easily break something(for example zoom or camera swiping with your ScrollView)
Frankly I'm not sure why are you doing this - you can easily place all the views you need in ordinary FrameLayout and everything will work fine(except maybe ScrollView swipe gesture processor may disrupt MapView gestures)
So it would be wiser do to it like this
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.company.com.library.mapbox.MyMapView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/mapView"/>
<FrameLayout
android:id="#+id/wrapper_layout"
android:layout_width="50dp"
android:layout_height="250dp"
android:layout_gravity="right"
android:layout_marginTop="100dp">
<ScrollView
android:id="#+id/level_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/level_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
</FrameLayout>
</FrameLayout>
This way you will be able to leverage all the possibilities of MapView and FrameLayout separately. Don't forget to handle lifecycle changes for the MapView in your fragment/activity as it is told here.
You may also notice that I wrapped ScrollView with FrameLayout and gave this wrapper layout wight and height, while ScrollView has match_parent. I've done that because ScrollView with defined height and width can be a real pain in the arse and is quite bug prone, thus wrapping it in some other layout is recommended workaround for such purposes.
While it is not the exact solution to your problem, I hope this answer will help you somehow.
My Problem:
I have a MainActivity along with its XML file activity_main.xml , which contains a NavigationDrawer view and that view calls a header.xml file to be displayed in my drawer.
The issue is that my header file contains a button so that when I click the header it opens a site. However since upgrading my Android studio build tools to 23.0.2 the onClick() for tht button inside my MainActivity crashes the app, giving me a NullPointerException.
I figure that its crashing because the header file is a totally different file from my activity_main.xml so my MainActivity would not have direct access to views inside of the header file.
How can I get access to the button that is inside the header.xml file with and also make it clickable?
Solved:
The NullPointerException was due to the fact that the layout(Header.xml) containing my Button was not readily available for the MainActivity's xml layout, therefore findViewById would always be null because to it, the button doesn't exist. This question was solved by including the header.xml with all its contents(specifically the button) into the NavigationView of the MainActivity.xml
Like so:
<android.support.v4.widget.DrawerLayout ....>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/toolbar"
layout="#layout/tool_bar" />
....
</RelativeLayout>
<android.support.design.widget.NavigationView
...
<include
layout="#layout/header" />
</android.support.v4.widget.DrawerLayout>
You can set the HeaderView of your NavigationView in your activity onCreate() method and set a listener to the header view like :
yourNavigationView.addHeaderView(yourHeaderView);
yourHeaderView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Handle the click event
}
});
Whenever I have Views inside a ViewGroup inside a android.support.v4.widget.DrawerLayout, Eclipse's autocomplete starts working weird. It doesn't display most of the properties
Example with DrawerLayout -> LinearLayout -> ImageView:
In the previous screenshot, you can see that I typed "android:scale..." and the IDE's intellisense isn't showing me the ImageView's android:scaleType
If I use Eclipse's Properties window for the ImageView, I can see that it is only displaying the basic properties for "View" (and not for ImageView...):
Now if the ImageView is not a descendant of the DrawerLayout and I put it somewhere else, the autocomplete works properly:
I've seen related questions such as:
Autocomplete does not work in XML files in particular hierarchy
Content Assist doesn't work in xml with support library
but they have been dead with no answers for quite a while...
Content assist doesn't work for Views (be it TextViews, EditText, Buttons...) that I add inside the DrawerLayout. It only suggests the 'basic' properties.
Does anybody know why this happens or how to fix this?
Sample layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/some_image" />
</LinearLayout>
<RelativeLayout
android:id="#+id/drawer_view"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start" >
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
Just to give some closure to this 5 months-old question, I'll quote and link to Atul O Holic's answer. Thanks to Dileep Perla for pointing me there.
When using support package Widgets this is a common scenario (a weird
one too).
Here you using, android.support.v4.widget.DrawerLayout and hence the
issue. Happened with me a lot of time.
You can also try couple of options mentioned here.
I've found that using the tag can be handy in this case. Just put your layout that is inside the drawer in a separate layout file and then include it inside the drawer layout.
My question is simple: How to disable any event on a View in Android? (including removing its focussability, like I just want it to be there visually but be inexistant on everything else)
And does it work on a whole view tree? (like if I disable events on the root, all the events will be disabled for its children?).
Now, before you say anything I have tried all the following:
setEnabled
setFocusable
setSelected
setClickable
setActivated
And none of these methods appear to work, seriously.
I have tried them directly on a WebView, as well as on the parent layout on everything but I am still able to interact with it.
Any idea?
Thanks!
EDIT#1
The solution that consists in adding a view on top of the view that needs to be disabled doesn't work. Actually, it's still possible to click on the inner view, I have tried with a simple example:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ff0000">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Click Me!"
/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
/>
</FrameLayout>
Here it's still possible to click on the button.
EDIT#2
The reason why I want to do this is related to the following question that I asked weeks ago.
What I have is a ListViewacting as a navigation bar which is underneath a View that holds the content of my app. The problem with this implementation is that when I try to scroll through the ListView when there is a focusable view in the layer on top of it, well the ListView doesn't scroll and instead it's the top view that takes focus (That's the case when there is a
Webview or an EditText etc.).
So yes as mentioned in one of the answers, I can disable any click events on a WebView by overriding setOnTouchListener but the view remains focussed and I think this is the reason why I am still having the same issue with my navigation bar.
Simply put a view on top of your view. You can toggle it on off by setting view.visibility = gone/visible.
<FrameLayout>
<WebView/>
<FrameLayout This view will be on top/>
</FrameLayout>
Edit: Just stumpled upon this link: https://stackoverflow.com/a/3856199/969325
Basically disables all touch event for the webview. Tryed that?
Edit 2 reedit: Try to set the visibility to gone for the the top view below your listview.