Crash during Fragment transactions inside the Custom Dialog in Xamarin Android - mono

When i tried to add a fragment inside a dialog, the app got crash. The crash saying "No View found for ID 0x01276"
This is the layout file for Dialog (my_dialog_layout.axml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
And this is the code for opening the dialog and for fragment transaction
class CustomDialog : Dialog{
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState)
SetContentView(Resource.Layout.dialog_fragment_layout);
var myCustomFragmnent = new MyCustomFragment(_context);
// Start Fragment Transaction Process
var transaction = FragmentManager.BeginTransaction();
// Here is a crash saying (No View found for ID 0x01276....)
transaction.Add(Resource.Id.fragment_container, myCustomFragmnent);
transaction.Commit();
}
}

Firstly you don't need to use a "heavy" layout such as LinearLayout, I suggest you use FrameLayout for your container.
Secondly, try to use transaction.Replace instead. Also make sure that MyCustomFragment does not blow up in OnCreateView. It might be where your problem lies as you didn't post the full stack trace.
When using transaction.Replace you can have it handle the backstack for you by adding:
transaction.AddToBackStack(null);
after your Replace call, such that when you press the back button on your phone it navigates back to the previous Fragment shown.

Related

How can I control navigation and backStack from main activity

I have two activities A and B and Three fragments C,D and E.
I used intent to move from activity A to B and didn't finish activity A as I want to get back to it later.
Activity B contains a custom layout and a fragment container.
Custom layout contains a text view and a back icon image view. This layout act as action bar as I do not use default action bar as theme of activity B is android:theme="#style/AppTheme.NoActionBar".
Fragment Container hosts a navigation graph.
Fragment C is Start destination and navigation graph allows navigation as C->D->E
and back stack in following order.
C->D //After first back Stack
C //After Second back Stack reached final element in back stack.
A //Activity B is finish and Activity A is resumed after pressing one more back icon image
On press back icon image view of custom layout in activity B xml.
As there is no other action bar in any Fragment(C, D, E) so I can only use back icon image view of activity B.
I want to know how I can achieve this functionality
My activity B xml is as follows
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="#+id/container"-->
<include layout="#layout/custom_tool_bar"
android:id="#+id/toolbar_settings_activity"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_dashboard_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/settings_navigation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar_settings_activity"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
xml code for custom tool bar is given bellow
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:background="#drawable/app_gradient_color_background">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/iv_back"
android:layout_width="20dp"
android:layout_height="26dp"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginEnd="1dp"
android:contentDescription="#string/content_description"
android:scaleType="fitXY"
android:src="#drawable/ic_white_color_back_24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
<LinearLayout
android:id="#+id/customlayout_width"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
app:layout_constraintStart_toEndOf="#+id/iv_back"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:id="#+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingEnd="10dp"
android:paddingTop="6dp"
android:paddingStart="10dp"
android:text="#string/custom_tool_bar_Name"
android:textColor="#color/colorOffWhite"
android:textSize="26sp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
custom layout used as action bar
Activity B when navgraph start destination is set to C fragment
Navgraph to navigate from fragment C->D->E in Activity B
1- First in your Activity B get the navController:
val navHostFragment = binding.navHostDashboardFragment.getFragment<NavHostFragment>()
val navController = navHostFragment.navController
2- Then you can add a click listener to your back button:
binding.toolbarSettingsActivity.ivBack.setOnClickListener {
val isStackPopped = navController.popBackStack() // Navigate back to the last fragment
if (!isStackPopped) finish() // If there is no fragments in the stack finish the activity and go back to activity A
}

Android Spinner text difference

I'm adding two different spinners to my XML layout, one thats filled through an XML file and one thats filled programmatically.
<Spinner
android:id="#+id/spHome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAlignment="textEnd" />
<Spinner
android:id="#+id/spDevice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:entries="#array/spinner_data"
android:textAlignment="textEnd" />
So the one Spinner is filled through this XML file, which goes great and gives a good clear text quality.
<resources>
<string-array name="spinner_data">
<item>Alle apparaten</item>
<item>Light</item>
<item>Door Sensor</item>
<item>Socket</item>
<item>Smart meter</item>
<item>Multi sensor</item>
</string-array>
<string-array name="solo_data">
<item>Hele huis</item>
</string-array>
The other spinner gets filled programmatically, with the following code:
private var roomDtoList: ArrayList<RoomItemDto> = ArrayList()
private var spRoomData : ArrayList<String> = ArrayList<String>()
private fun fillSpRooms(){
spRoomData.clear()
for(item in roomDtoList){
spRoomData.add(item.name)
}
var spAdapter : ArrayAdapter<String> = ArrayAdapter<String>(this.context, R.layout.spinner_drop_layout, R.id.spinnerTextview, spRoomData)
spHome!!.adapter = spAdapter
}
So whenever I fill this spinner with the following code, the filled text looks ugly and has no margin/spacing between every line. Even when I add margin and textStyling into the R.id.spinnerTextview, it won't make the text look clear.
Anyone knows a fix?
Try doing this. Hope this will help.
for(item in roomDtoList){
spRoomData.add(item.name)
}
spHome!!.setOnItemSelectedListener(this)
// Create an ArrayAdapter using a simple spinner layout and languages array
val aa = ArrayAdapter(this, android.R.layout.simple_spinner_item, spRoomData)
// Set layout to use when the list of choices appear
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
// Set Adapter to Spinner
spHome!!.setAdapter(aa)

Xamarin forms Android how We change Tabbed Page Icon Size

Xamarin forms Android how We change Tabbed Page Icon Size. I have Using AppCompact Themes and I want Increase Tabbed Page icon size in Tabbar.axaml
You can create a Custom renderer and change the size of icon in the native platform. Actually you can override the whole tab's layout.
For example, in PCL first create a class inherit from TabbedPage:
public class MyTabbedPage : TabbedPage
{
}
Then create its renderer in Android project for example like this:
[assembly: ExportRenderer(typeof(MyTabbedPage), typeof(MyTabbedPageRenderer))]
namespace YourNameSpace.Droid
{
public class MyTabbedPageRenderer : TabbedPageRenderer
{
protected override void SetTabIcon(TabLayout.Tab tab, FileImageSource icon)
{
base.SetTabIcon(tab, icon);
tab.SetCustomView(Resource.Layout.mytablayout);
var imageview = tab.CustomView.FindViewById<ImageView>(Resource.Id.icon);
imageview.SetBackgroundDrawable(tab.Icon);
}
}
}
The layout I created is like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="fitCenter"
android:id="#+id/icon"
android:layout_gravity="center_horizontal" />
</LinearLayout>
As you can see, I set the size directly in the axml file.
When you want to use this custom TabbedPage, you can for example code like this:
<local:MyTabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabbedPageForms"
x:Class="TabbedPageForms.MainPage">
<local:TodayPage Title="Today" Icon="hamburger.jpg" />
<local:SchedulePage Title="Schedule" Icon="hamburger.jpg" />
</local:MyTabbedPage>
Code behind:
public partial class MainPage : MyTabbedPage
{
public MainPage()
{
InitializeComponent();
}
}

Glide Cache management in Recyclerview with Grid layout

I am trying to build a gallery for my app. Following some tutorials and stackoverflow, I finally managed to make the gallery. I am using Glide to set images, so no issue of memory crashing and all. The only problem is, when I fling, Images are not set into their views as fast as those views are being shown. Here is a gif. So I get to see the placeholders or the background of the recyclerview while imageviews are being set. Depending on the fling speed, this may last for 500-1000ms. But that is sufficient to make the gallery look bad. This happens when I use fling to scroll up or down. To my knowledge, this is because glide freeing the images from it's cache. Is there any solution for it.
Here is my code.
activity_gallery:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/activity_monuments"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".GalleryActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_gallery"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:alwaysDrawnWithCache="true"
android:clipToPadding="false"
android:scrollbars="vertical"
android:scrollbarStyle="insideOverlay"/>
</LinearLayout>
Here is how I am setting recyclerview:
RecyclerView gridView = (RecyclerView)findViewById(R.id.recyclerview_gallery);
gridView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getApplicationContext(),NUM_OF_COLUMNS);
gridView.setLayoutManager(layoutManager);
gridView.isDrawingCacheEnabled();
gridView.addItemDecoration(new MarginDecoration(GalleryActivity.this, NUM_OF_COLUMNS, GRID_PADDING, true));
gridView.setHasFixedSize(true);
gridView.setVerticalScrollBarEnabled(true);
gridView.setBackgroundColor(getResources().getColor(R.color.colorBlack));
GalleryAdapter galleryAdapter = new GalleryAdapter(GalleryActivity.this, GalleryActivity.this, ImageNamesList, columnWidth);
gridView.setAdapter(galleryAdapter);
Here is how I am setting imageview in adapter:
viewHolder.galleryImage.setLayoutParams(new GridView.LayoutParams(imageWidth, imageWidth));
Glide.with(context)
.load(uri)
.asBitmap()
.placeholder(R.drawable.monument)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(viewHolder.galleryImage);
Please let me know of the possible solutions.
P.S: The gif is low frame rate and hence showing the slow fling which is not the case.
To solve cache management, i use a singleton store best practice. Realm for android is perfect it is NoSql and super fast, what i normally do is create a realm object, in the adapter check if the current url is in realm, if true dont pull new image else, pull and store.
Then when the main activity or fragment is ever being destroy just delete all from realm.

Problems loading AdView inside a RecyclerView

I've been looking in Stackoverflow how to integrate an AdView inside a RecyclerView. I've been following these posts:
One, two
Basically the way to do it is calling loadAd inside onCreateViewHolder or inside the constructor of the ViewHolder.
Either way, this is my implementation:
JAVA
public class AdExpressViewHolder extends RecyclerView.ViewHolder {
public AdExpressViewHolder(View itemView) {
super(itemView);
final AdView adView = (AdView)itemView.findViewById(R.id.adView);
AdRequest request = new AdRequest.Builder()
.build();
adView.loadAd(request);
}
}
XML
<?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"
xmlns:ads="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<com.google.android.gms.ads.AdView
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
ads:adUnitId="**********************"
ads:adSize="BANNER">
</com.google.android.gms.ads.AdView>
</RelativeLayout>
</RelativeLayout>
The problem is: when I scroll the RecyclerView, it seems to load on the UI thread since it gets stuck, only the first time. The rest of the times is ok.
This is the video that demonstrates it:
Video
As you can see, the first one is blocking the UI, but not the second one.
What am I doing wrong?
Thank you in advance.
EDIT
I've tried to load a conventional AdView in an activity, fixed. It works and it doesn't seem to be load in the UI Thread. Seems it's just happening in the RecyclerView.
After 3 weeks, I've done a Method profiling, and this is what I've got out:
You can realise the red spots. Those are 2 different AdView loading, while the rest are 38 normal custom views of mine.
To be more concrete, these are the functions, so it's regarding 100% the AdView:
It seems a bug of the Ads SDK for Android and it's not been fixed, at least until v9.4.0.
More information here:
https://groups.google.com/forum/#!searchin/google-admob-ads-sdk/ui$20thread%7Csort:relevance/google-admob-ads-sdk/k4IFZA_QGT4/3gMHaCPPBQAJ