Rotate drawable has not effect - kotlin

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.

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>

How to use LottieAnimationView in SharedElementTransition?

I decided to use Lottie animation to switch from activity to activity.
My animation covers the entire screen, and I would like to have half the animation time played on the first activity and the rest on the second activity
I tried using Shared Element Transition but it doesn't work properly because when new activity starts first what i see is new activity and then after few miliseconds Lottie animation resumes. I would like to avoid showing new activity before Lottie animation is over
First Activity XML file
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.airbnb.lottie.LottieAnimationView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/newActivityAnimation"
app:lottie_fileName="transitionAnimation.json"
android:scaleType="centerCrop"
android:elevation="5dp"
android:transitionName="sharedNewActivityTransition"
/>
Second Activity XML file
<RelativeLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MenuActivity">
<com.airbnb.lottie.LottieAnimationView android:layout_width="match_parent"
android:layout_height="match_parent"
app:lottie_fileName="transitionAnimation.json"
android:scaleType="centerCrop"
android:id="#+id/changeActivityAnimationMenu"
android:elevation="5dp"
android:transitionName="sharedNewActivityTransition"
/>
</RelativeLayout>
Here is function which start changing activite
override fun onLanguageClickListener(position: Int) {
animateCollapseMenuSlide(isMenuCollapsed)
newActivityAnimation.setMaxFrame(19)
delay.delayedFunction({newActivityAnimation.playAnimation()},200)
delay.delayedFunction({changeActivity()},1000)
}
.
.
.
private fun changeActivity() {
val intent = Intent(this,MenuActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NO_ANIMATION
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(this,activityTransitionAnimation,
"sharedNewActivityTransition")
startActivity(intent,options.toBundle())
}

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

Animation rotation off axis

I'm trying to create a custom "loading/throbber" icon for my app. I have an ImageView that points to my "loading" icon:
The problem is the rotation is off axis and looks "wobbly", but I'm not sure what I'm doing wrong:
<ImageView
android:id="#+id/headerReload"
android:src="#drawable/reload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dip"
android:onClick="headerReload_onClick"
android:layout_alignParentRight="true"
/>
public void headerReload_onClick(final View v) {
ImageView searchSpinner = (ImageView)findViewById(R.id.headerReload);
Animation spinnerAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.loading);
searchSpinner.startAnimation(spinnerAnimation);
}
loading.xml
<?xml version="1.0" encoding="UTF-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:interpolator="#android:anim/linear_interpolator"
android:duration="1200"
/>
5dp padding on the right side will cause it to rotate unevenly