Problems loading AdView inside a RecyclerView - android-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

Related

Kotlin textview to scroll in both directions

I'm trying to setup a textView in Kotlin to scroll in both directions (ie horizontal and vertical).
That is, I want long lines to run off the right side, and user should be able to scroll/drag to the right to see.
Additionally, when there's enough text to run off the bottom of the view, they should be able to scroll down as well. So basically a small "window viewer" if you will to a larger document.
(I'm doing this as the text displayed is a specific/strict format, and the "window" is limited in size).
I found a few questions talking about it, however, all suggestions I've found so far have not worked.
here's what I have so far:
activity_main.xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginStart="105dp"
android:layout_marginTop="90dp"
android:scrollbars="horizontal|vertical"
android:scrollHorizontally="true"
android:text="This is line 1 and should scroll off the view to the right. \n \n This is line 2 and again should scroll off the view tot he right. \n \n This is line 3.\n and these \n lines should \n scroll off\n the bottom \n of the view\n when it\n gets long\n enough to \n pass the\n bottom of\n the view\n "
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.util.Log
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var txtVw = findViewById<TextView>(R.id.textView )
txtVw.movementMethod = ScrollingMovementMethod()
}
}
Is there an easy way to do this? or will I have to start playing with a Horizontal Scroll View and ScrollView ??
which ends up with thsi:
Scrolling up/down fine .. however, you see the first 2 lines wrap around.
If I use "single line" property, of course the entire textView goes 1 line, so that doesn't help.
What am I missing?
Read over the info on textView, but couldn't find anything useful on scrolling horizontally.
As Cheticamp mentioned, you should add a HorizontalScrollView around your TextView. If you want to do this programmatically you could do:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myHorizontalScrollView = HorizontalScrollView(this)
var txtVw = findViewById<TextView>(R.id.textView)
//since your textview already has a parent (the constraintlayout from the main_activity.xml file) you have to remove the widget from is parent first, before you add it in another layout.
(txtVw.parent as ConstraintLayout).removeView(txtVw)
myHorizontalScrollView.addView(txtVw)
// before doing this you must give an id to your ConstraintLayout
findViewById<ConstraintLayout>(R.id.myConstraint).addView(myHorizontalScrollView)
}
}
Or you could modify your activity_main.xml file to look like this:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginStart="105dp"
android:layout_marginTop="90dp"
android:scrollbars="horizontal|vertical"
android:scrollHorizontally="true"
android:text="This is line 1 and should scroll off the view to the
right. \n \n This is line 2 and again should scroll off the view
to the right. \n \n This is line 3.\n and these \n lines should \n
scroll off\n the bottom \n of the view\n when it\n gets long\n
enough to \n pass the\n bottom of\n the view\n "
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</HorizontalScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

Rotate drawable has not effect

The starting point here is the need to periodically rotate a vector drawing, like for instance the hands of an analog clock.
I understand that a vectorDrawable resource does not directly support rotation attributes. I can put the drawable inside a group which can rotate the drawable, but that rotation won't be modifiable at run time.
I came across many posts explaining rotating views or canvases, as well as the rotate drawable. The latter seems to be appropriate for my purpose.
I created a new activity with the help of Android Studio 3.5 to achieve a simple rotation with the help of a rotate drawable.
java/com.example.myapplication/MainActivity:
package com.example.myapplication
import android.graphics.drawable.RotateDrawable
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val activity = this#MainActivity
val context = activity.applicationContext
val drawable = ContextCompat.getDrawable(context, R.drawable.rotation)
val rotation = drawable as RotateDrawable
rotation.setLevel(180)
}
}
res/layout/activity_main.xml:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/rotation" />
</androidx.constraintlayout.widget.ConstraintLayout>
res/drawable/rotation.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%" android:pivotY="50%"
android:fromDegrees="0" android:toDegrees="360"
android:drawable="#drawable/ic_launcher_foreground"/>
I expect that the setLevel function can be used to rotate the drawable, but it has no effect.
Changing the fromDegrees attribute in the rotation.xml does the rotation as expected. I am not sure if the maximum level for <rotate> should be 360 or 10000, but that is not the issue.
What am I missing? Is it a detail, or is the rotateDrawable the wrong approach altogether?
Related questions:
Rotating a drawable in Android
Programmatically rotate drawable or view
Is it possible to rotate a drawable in the xml description?
Try using imageView2.setRotation(180) instead of rotation drawable.

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)

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.

Crash during Fragment transactions inside the Custom Dialog in Xamarin Android

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.