Gif blinking in RecyclerView using Fresco - android-recyclerview

I use Fresco to load gif in a Recyclerview.
Here is my kotlin code:
fun loadResizeImage(uri: Uri, view: SimpleDraweeView, width: Int, height: Int) {
val request = ImageRequestBuilder.newBuilderWithSource(uri)
.setResizeOptions(ResizeOptions(width, height)).build()
val controller = Fresco.newDraweeControllerBuilder()
.setOldController(view.controller)
.setImageRequest(request)
.build()
view.controller = controller
I don't play the gif, I just load it as a static image. But when I invoke notifydatasetchanged, the gif blinks.
I have set the supportsChangeAnimations to false, and only the gif is blinking. Can anyone help me?

My solution is to set tag to the view, if the tag equals to the uri i won't reload the image. But I find when i invoke notifyDataSetChange, the tag i set to the view is changed.but when I invoke notifyItemChanged,it doesn't.I have no idea why the tag changed(i didn't scroll the RecyclerView).

Related

howTo get Image Resource of a ImageButton in kotlin

i want change the ImageResource of a ImageButton that i have find by id.
Motivation
a ImageButton(bottom) works as a reminder/backup of the last click of a ImageButton(top) .
setup:
some ImageButton (at the top of the app).
a ImageButton (at the bottom of the app).
example without errors, but don't find ImageResource of idR1
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageResource(R.drawable.athen_cavalry_swordsman);
not working examples
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageResource(it.resources.getDrawable());
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageResource(it.getImageResource());
try to get and set Drawable
following causes the app to crash when i click on an ImageButton.
Here i use a defType "res" to get the resource (the image hopefully).
val resR1: Int = resources.getIdentifier("r1col$i", "res", this.packageName)
findViewById<ImageButton>(idR1).setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageDrawable(getDrawable(resR1))
How could i get this image resource of it ? And use it for the other ImageButton?
You should be setting the image like using setImageDrawable like this.
val image = findViewById<ImageButton>(R.id.your_view_id)
image.setOnClickListener {
findViewById<ImageButton>(idR5_oppCiv).setImageDrawable(image.drawable)
}

Adapter with Picasso

I'm trying to use Picasso to get images from Url and put inside an Adapter. I have to send the image as a parameter to the funcion imageSlider inside the my SliderViewHolder. Can someone explain me how?
Picasso get:
Picasso.get()
.load(sliderImages[position])
.transform( RoundedTransformation(30, 0))
.placeholder(context.resources.getDrawable(R.drawable.ic_launcher_foreground))//it will show placeholder image when url is not valid.
.networkPolicy(NetworkPolicy.OFFLINE) //for caching the image url in case phone is offline
.into(holder.imageSlider(?))
Viewholder:
class SliderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: RoundedImageView = itemView.findViewById(R.id.image_slide)
fun imageSlider(sliderItem: SliderItem) {
imageView.setImageResource(sliderItem.image)
}
}
The Function
fun imageSlider(sliderItem: SliderItem) {
imageView.setImageResource(sliderItem.image)
}
is not necessary, because you declare the imageView with a public visibility.
In the Adapter of your RecyclerView, there is a Method called
override fun onBindViewHolder(holder: SliderViewHolder, position: Int)
This one will get invoked, when the Adapter wants to bind your Item Layout (ViewHolder) with a "backing data item" of the List...
Then you could simply do this:
Picasso.get()
.load(sliderImages[position])
.transform( RoundedTransformation(30, 0))
.placeholder(context.resources.getDrawable(R.drawable.ic_launcher_foreground))//it will show placeholder image when url is not valid.
.networkPolicy(NetworkPolicy.OFFLINE) //for caching the image url in case phone is offline
.into(holder.imageView)
Which will make Picasso, load the Image into the ImageView of your ViewHolder (which actually simply holds the Item Layout) for the current Item in the List.
The correct implementation would actually be, that you give your Adapter a List of Image Objects (for example, containing Properties like Image Name and a Path/URL, that should get "rendered") and when the Adapter is invoking "onBindViewHolder" with the corresponding Position, it is your Job to implement the loading of the image from the given path for the given position.

Override width to the half of the screen

I am developing a chat and i use Recyclerview to show the messages. When the message is an image i use Glide to display it. Using glide i use the override function to show the image with specific dimensions. However this does not work very good because not all the phones have the same resolution and size.
bitmap?.let {
//meaning the image is landscape view
if (bitmap.width > bitmap.height)
Glide.with(Application.instance)
.load(fileInfo.localUri)
.apply(RequestOptions().override(500, 250))
.into(holder.sntImageView)
else
Glide.with(Application.instance)
.load(fileInfo.localUri)
.apply(RequestOptions().override(250, 500))
.into(holder.sntImageView)
holder.sendingProgress.visibility = View.GONE
holder.sntBubble.visibility = View.GONE
holder.sntImageView.visibility = View.VISIBLE
} ?: run {
holder.sntImageView.visibility = View.GONE
holder.sendingProgress.visibility = View.GONE
holder.sntBody.text = "Unable to decode image"
}
So my question is how to use Glide so that the image has almost the half of the screen instead of 500, 250...?
You can start by knowing the with of your container, like recyclerviews width:
container.width
This will give you the width in pixels. After that you can apply a division to get the pixels at half:
val yourViewWidth = container.width / 2
That's how you make it to half of the container.
And then you just have to pass that value to Glide.
If you want to get total device width, you can get the pixels like this accepted answer and then apply the same division criteria.
Note that if you are in a recyclerview and want to know the size of a child view, you may need to wait the layout to be ready in order to have access to its parameters. That can be done with the ViewTreeObserver.OnGlobalLayoutListener, And do your operations inside onGlobalLayout. It will be triggered when the view is ready and you'll be able to operate there.
Hope it helps, happy coding!

Kotlin download and display a PDF

Hi I would like to download and display a pdf using Kotlin. I want to download and display a progress bar with the first page of the pdf display while we are downloading.Then display the PDF. I did it in swift with PDFKit it was very simple but I can't find an equivalent in Kotlin.
I made many research to display a pdf in Kotlin but I didn't got much result, it's seem that this subject is not really so first I looked at PdfRenderer that is native but most exemple are in java and not Kotlin and I don't get what is : documented.getSeekableFileDescriptor().
Then I looked at pdfView lib that is really nice to display a pdf but only from asset, the pdfView.fromStream doesn't seem to work and I can't get any exemple to how it's work.More over I would like to avoid downloading the pdf I want to display it directly to avoid long loading.
Finaly I used okhttp and retrofit to download the pdf but I can't use pdfView to display it because in the from asset the pdf has to be already in the project.
I found that downloading pdf from and url and display it with Kotlin is very difficult and not very documented.
So if anyone has some suggestion I'll take it.
here is my sample of code using pdfView.fromStream this only load a blanc page
private fun loadpdf(){
println("pdfview")
//PDF View
Thread(Runnable {
val input = URL(pdf_url).openStream()
val pdfView = this.findViewById<PDFView>(com.example.mylibrary.R.id.pdfView)
//pdfView.fromFile(file)
pdfView.fromStream(input)
.enableSwipe(true) // allows to block changing pages using swipe
.swipeHorizontal(true)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(false) // render annotations (such as comments, colors or forms)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true) // improve rendering a little bit on low-res screens
// spacing between pages in dp. To define spacing color, set view background
.spacing(0)
.pageFitPolicy(FitPolicy.WIDTH)
.load()
println("testpdf")
})
}
And here is my sample of code using pdfView.fromAsset this one work but only if the file is already on the project however I want to get my pdf from and url
private fun loadpdf(){
//PDF View
Thread(Runnable {
val pdfView = this.findViewById<PDFView>(com.example.mylibrary.R.id.pdfView)
pdfView.fromAsset("url")
.enableSwipe(true) // allows to block changing pages using swipe
.swipeHorizontal(true)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(false) // render annotations (such as comments, colors or forms)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true) // improve rendering a little bit on low-res screens
// spacing between pages in dp. To define spacing color, set view background
.spacing(0)
.pageFitPolicy(FitPolicy.WIDTH)
.load()
})
}
If anyone got this problem, I solved it by using the coroutine :
Add this dependency to your gradle build :
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2")
then import this line :
import kotlinx.coroutines.*
in your file.
Then use launch coroutine methods as follow :
private fun loadpdf(pdfView: PDFView){
//PDF View
GlobalScope.launch{
val input : InputStream
input = URL(pdf_url).openStream()
pdfView.fromStream(input)
.enableSwipe(true) // allows to block changing pages using swipe
.swipeHorizontal(true)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(false) // render annotations (such as comments, colors or forms)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true) // improve rendering a little bit on low-res screens
// spacing between pages in dp. To define spacing color, set view background
.spacing(0)
.pageFitPolicy(FitPolicy.WIDTH)
.load()
}
You have to pass the pdfView cos you can use the global view in asyctask.
Now to add a progress bar you can add to your xml :
<ProgressBar
android:id="#+id/Progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:indeterminate="true"
android:minWidth="200dp"
android:minHeight="50dp" />
then you need to override the function loadComplete to get the call back for your progress bar and implement OnLoadCompleteListener interface for your activity.
And btw if you want to display page per page with the pdfView lib add :
.swipeHorizontal(true)
.pageSnap(true)
.autoSpacing(true)
.pageFling(true)

Object detection from image using vision framework

I am trying to detect objects from a given image. From research I just found that we can detect and track an object for the videos using the following process:
private lazy var cameraLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
private func tapGestureAction(recognizer: UITapGestureRecognizer)
{
highlightView.frame.size = CGSize(width: 200, height: 200)
highlightView.center = recognizer.location(in: view)
let originalRect = highlightView.frame
var convertedRect = cameraLayer.metadataOutputRectConverted(fromLayerRect: originalRect)
convertedRect.origin.y = 1 - convertedRect.origin.y
previousObservation = VNDetectedObjectObservation(boundingBox: convertedRect)
}
Can we have similar method like metadataOutputRectConverted for imageView? I am trying to detect the object rect whenever the user taps on that object. How can this be accomplished?
this method to convert the camera output rect ( topleft(0,0) to bottomright(0,1)) to the UI rect. So, I think you do not need to convert it