Is it possible to display animated gif in jetpack? - user-interface

I'm trying to implement a gif in my splash screen using jetpack.Tried this one as suggested but no output .What am I missing?
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
if (SDK_INT >= 28) {
add(ImageDecoderDecoder(context))
} else {
add(GifDecoder())
}
}
.build()
Image(
painter = rememberImagePainter(
imageLoader = imageLoader,
data = R.id.mygif,
builder = {
size(OriginalSize)
}
),
contentDescription = null,
modifier = Modifier
.padding(top = 100.dp)
)

Apparently Compose is not supporting gif out of the box, I could not find any reference to gif files in the docs. However, one of the popular library out there to deal with gifs is Coil.
-> Here is coil for Compose:
https://coil-kt.github.io/coil/compose/
-> Make sure to add the gif extension:
https://coil-kt.github.io/coil/gifs/
-> You will have to override the ImageLoader and add the gif extension:
https://coil-kt.github.io/coil/compose/#localimageloader

For those, who is still looking for answer, here is updated version (since LocalImageLoader is deprecated) in Coil.
Same steps for installation:
Add implementation for coil-compose
Add implementation for coil-gif
Usage:
#Composable
fun Content() {
val imageLoader = ImageLoader.Builder(LocalContext.current)
.components {
if (SDK_INT >= 28) {
add(ImageDecoderDecoder.Factory())
} else {
add(GifDecoder.Factory())
}
}
.build()
Image(
painter = rememberAsyncImagePainter(
ImageRequest.Builder(LocalContext.current)
.data(data = R.drawable.mettaton_battle_box)
.apply(block = fun ImageRequest.Builder.() {
size(Size.ORIGINAL)
}).build(),
imageLoader = imageLoader
),
contentDescription = null,
)
}

Related

Wear OS Button Background

Button(
onClick = {
raceOn = !raceOn
if (raceOn) {
text.value = "Stop!"
color.value = Color.Red
} else {
text.value = "Go!"
color.value = Color.Green
}
},
modifier = Modifier.background(color = color.value),
content = {
Text(
text = "${text.value}",
)
}
)
Using the code above, I got the attached image. What I want is the inside of the button to be green and not the background behind it. I couldn't the right property to modify.
Has anyone here tried to modify the Button background? Or perhaps suggest another solution. I tried the OutlinedButton and wasn't successful.
Thanks!
Use the MaterialTheme ButtonColors.
val colors: ButtonColors = ButtonDefaults.primaryButtonColors(backgroundColor = Color.Red)
Button(onClick = { /*TODO*/ }, colors = ButtonDefaults.primaryButtonColors()) {
// TODO
}
You can also update via setting the MaterialTheme defaults.
val wearColorPalette: Colors = Colors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200,
secondaryVariant = Teal200,
error = Red400,
onPrimary = Color.Black,
onSecondary = Color.Black,
onError = Color.Black
)
...
MaterialTheme(
colors = wearColorPalette,
typography = Typography,
// For shapes, we generally recommend using the default Material Wear shapes which are
// optimized for round and non-round devices.
content = content
)

How to make Jetpack Compose Image animating infinite

I have an animated-vector drawable.
I want this animated vector to be animated in loop while this image is showing.
Cannot find a good solution for this.
val image = animatedVectorResource(R.drawable.no_devices_animated)
var atEnd by remember { mutableStateOf(false) }
Image(
painter = image.painterFor(atEnd),
"image",
Modifier.width(150.dp).clickable {
atEnd = !atEnd
},
contentScale = ContentScale.Fit)
When I tap on the image it is animating but then stops. This is kind of an infinite progress.
Leaving my solution here (using compose 1.2.0-alpha07).
Add the dependencies in your build.gradle
dependencies {
implementation "androidx.compose.animation:animation:$compose_version"
implementation "androidx.compose.animation:animation-graphics:$compose_version"
}
And do the following:
#ExperimentalAnimationGraphicsApi
#Composable
fun AnimatedVectorDrawableAnim() {
val image = AnimatedImageVector.animatedVectorResource(R.drawable.avd_anim)
var atEnd by remember { mutableStateOf(false) }
// This state is necessary to control start/stop animation
var isRunning by remember { mutableStateOf(true) }
// The coroutine scope is necessary to launch the coroutine
// in response to the click event
val scope = rememberCoroutineScope()
// This function is called when the component is first launched
// and lately when the button is pressed
suspend fun runAnimation() {
while (isRunning) {
delay(1000) // set here your delay between animations
atEnd = !atEnd
}
}
// This is necessary just if you want to run the animation when the
// component is displayed. Otherwise, you can remove it.
LaunchedEffect(image) {
runAnimation()
}
Image(
painter = rememberAnimatedVectorPainter(image, atEnd),
null,
Modifier
.size(150.dp)
.clickable {
isRunning = !isRunning // start/stop animation
if (isRunning) // run the animation if isRunning is true.
scope.launch {
runAnimation()
}
},
contentScale = ContentScale.Fit,
colorFilter = ColorFilter.tint(Color.Red)
)
}
Case you need to repeat the animation from the start, the only way I find was create two vector drawables like ic_start and ic_end using the information declared in the animated vector drawable and do the following:
// this is the vector resource of the start point of the animation
val painter = rememberVectorPainter(
image = ImageVector.vectorResource(R.drawable.ic_start)
)
val animatedPainter = rememberAnimatedVectorPainter(
animatedImageVector = AnimatedImageVector.animatedVectorResource(R.drawable.avd_anim),
atEnd = !atEnd
)
Image(
painter = if (atEnd) painter else animatedPainter,
...
)
So, when the animated vector is at the end position, the static image is drawn. After the delay, the animation is played again. If you need a continuous repetition, set the delay as the same duration of the animation.
Here's the result:
Infinite loop without static images solution:
Best working with animated vector drawable that is a loop.
First add the dependencies in your build.gradle
dependencies {
implementation "androidx.compose.animation:animation:$compose_version"
implementation "androidx.compose.animation:animation-graphics:$compose_version"
}
Animated loop loader
#OptIn(ExperimentalAnimationGraphicsApi::class)
#Composable
fun Loader() {
val image = AnimatedImageVector.animatedVectorResource(id = R.drawable.loader_cycle)
var atEnd by remember {
mutableStateOf(false)
}
val painterFirst = rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd)
val painterSecond = rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = !atEnd)
val isRunning by remember { mutableStateOf(true) }
suspend fun runAnimation() {
while (isRunning) {
atEnd = !atEnd
delay(image.totalDuration.toLong())
}
}
LaunchedEffect(image) {
runAnimation()
}
Image(
painter = if (atEnd) painterFirst else painterSecond,
contentDescription = null,
)
}
Right now I don't see any option to restart painter to start all over again - you need to rewind it. So in this solution we create two of those painter. One of them is starting with !atEnd. Each time atEnd is changed both of them do their work but we display only one animating from start to end. The other one is silently rewinding the animation.
According to https://developer.android.com/jetpack/compose/resources#animated-vector-drawables
val image = AnimatedImageVector.animatedVectorResource(R.drawable.animated_vector)
val atEnd by remember { mutableStateOf(false) }
Icon(
painter = rememberAnimatedVectorPainter(image, atEnd),
contentDescription = null
)
To make the animation loop infinitely:
val image = AnimatedImageVector.animatedVectorResource(id = vectorResId)
var atEnd by remember { mutableStateOf(false) }
Image(
painter = rememberAnimatedVectorPainter(animatedImageVector = image, atEnd = atEnd),
contentDescription = null,
)
LaunchedEffect(Unit) {
while (true) {
delay(animDuration)
atEnd = !atEnd
}
}
I tried to implement a loading spinner using this approach, but encountered some issues.
I had an issue with the proposed solution, where the animation reverses back to the beginning. To prevent this, as #nglauber suggested, I tried switching to a static vector when the animation ends. Unfortunately, that wasn't smooth as the animation would have to wait for the delay before restarting.
This was the workaround that I used.
#OptIn(ExperimentalAnimationGraphicsApi::class)
#Composable
fun rememberAnimatedVectorPainterCompat(image: AnimatedImageVector, atEnd: Boolean): Painter {
val animatedPainter = rememberAnimatedVectorPainter(image, atEnd)
val animatedPainter2 = rememberAnimatedVectorPainter(image, !atEnd)
return if (atEnd) {
animatedPainter
} else {
animatedPainter2
}
}

Transparent view

I would like to create a View (stage, window) with partially transparent background. I have an image containing alpha channel
I used this kind of scenes in JavaFx, where I had to set the scene fill to null and the root node background color to transparent. I tried the same with TornadoFX:
class NextRoundView : View("Következő kör") {
override val root = vbox {
style {
backgroundColor = multi(Color.TRANSPARENT)
backgroundImage = multi(URI.create("/common/rope-bg-500x300.png"))
backgroundRepeat = multi(BackgroundRepeat.NO_REPEAT
to BackgroundRepeat.NO_REPEAT)
}
prefWidth = 500.0
prefHeight = 300.0
spacing = 20.0
padding = insets(50, 20)
text("A text") {
font = Font.font(40.0)
alignment = Pos.CENTER
}
button("OK")
{
font = Font.font(20.0)
action {
close()
}
}
sceneProperty().addListener{ _,_,n ->
n.fill = null
}
}
}
I'm calling the view like this:
NextRoundView().apply {
openModal(stageStyle = StageStyle.TRANSPARENT, block = true)
}
However, the stage is still has background:
What have I missed?
You've made a couple of mistakes that causes this. First of all, you must never manually instantiate UICompoenents (View, Fragment). Doing so will make them miss important life cycle callbacks. One important callback is onDock, which is the perfect place to manipulate the assigned scene. Changing these two issues and also cleaning up some syntax leads to this code, which successfully makes the background transparent:
class MyApp : App(MyView::class)
class MyView : View() {
override val root = stackpane {
button("open").action {
find<NextRoundView>().openModal(stageStyle = StageStyle.TRANSPARENT, block = true)
}
}
}
class NextRoundView : View("Következő kör") {
override val root = vbox {
style {
backgroundColor += Color.TRANSPARENT
backgroundImage += URI.create("/common/rope-bg-500x300.png")
backgroundRepeat += BackgroundRepeat.NO_REPEAT to BackgroundRepeat.NO_REPEAT
}
prefWidth = 500.0
prefHeight = 300.0
spacing = 20.0
padding = insets(50, 20)
text("A text") {
font = Font.font(40.0)
alignment = Pos.CENTER
}
button("OK") {
font = Font.font(20.0)
action {
close()
}
}
}
override fun onDock() {
currentStage?.scene?.fill = null
}
}
Here is a screenshot of the app with the changes implemented:

Flutter/Dart resizing an Image in actual device took > 10 mins

I discovered a behaviour with Flutter/Dart. I am trying to resize an image from the ImagePicker.
The simulator works well but on the actual device, an iPhone 6 plus, the whole process took more than 10 mins and ended with a crash.
On the actual device, I clicked on the button that brings out the Image Picker, I select a photo and the device just hung. After 10 mins, the Image Pciker dismisses and continues with the image resizing and after 5 mins or so, it crashes.
Here is the code:
ImagePicker.pickImage(source: source)
.then((_imageFile2) => _uploadFile(_imageFile2)
.then((downbloadURL) {
if (downbloadURL != null ) {
createCloudStoreRecord(fireBaseUser, downbloadURL, true);
setState(() {
profileImage = new DecorationImage(
image: getProfileImage(downbloadURL),
fit: BoxFit.cover,
);
});
Navigator.pop(context);
showInSnackBar("Image Updated");
} else {
Navigator.pop(context);
showInSnackBar("Image Update Error!");
}
}));
Future<String> _uploadFile(_imageFile2) async {
print("in upload image");
if (_imageFile2==null) {
print("imagePicker image is null");
Navigator.pop(context);
return null;
} else {
onLoading(context, "Updating ...");
try {
// resize image
Im.Image image = Im.decodeImage(_imageFile2.readAsBytesSync());
Im.Image smallerImage = Im.copyResize(image, 500); // choose the size here, it will maintain aspect ratio
final tempDir = await getTemporaryDirectory();
final path = tempDir.path;
var filename = user.uid.toString() + ".png";
var newPath = '$path/' + filename;
print("start compressed");
var compressedImage = new File(newPath)..writeAsBytesSync(Im.encodePng(smallerImage));
print("end compressed");
//final Directory systemTempDir = Directory.systemTemp;
final StorageReference ref = FirebaseStorage.instance.ref().child('users/' + filename);
final StorageUploadTask uploadTask = ref.putFile(
compressedImage,
new StorageMetadata(
contentLanguage: 'en',
customMetadata: <String, String>{'renalbase': 'user_photo'},
),
);
print("Start upload");
UploadTaskSnapshot uploadSnapshot = await uploadTask.future;
print("image uploaded");
Map<String, dynamic> pictureData = new Map<String, dynamic>();
pictureData["url"] = uploadSnapshot.downloadUrl.toString();
print("Bfore url = ${pictureData["url"]}");
final RegExp regExp = RegExp('.*(?=\\?)');
pictureData["url"] = Uri.decodeFull( regExp.stringMatch(pictureData["url"]) );
print("url = ${pictureData["url"]}");
return pictureData["url"];
} catch(e) {
print("Upload error: $e");
showInSnackBar("Upload error: $e");
return null;
}
}
}
I had similar issues with image resizing taking too long. I switched to using the maxHeight and maxWidth parameters in ImagePicker.pickImage and have had far better results.
_imageFile = await ImagePicker.pickImage(
source: ImageSource.gallery,
maxHeight: 450.0,
maxWidth: 450.0);
Gave up on the image plugin and used the flutter_native_image instead.
(https://github.com/btastic/flutter_native_image)
Works like a charm.
Neither flutter_native_image or ImagePicker works well in all cases...
flutter_native_image resize the picture by x-percent when you just call the quality parameter... what a mess, this is not the intended purpose !!!
and image_picker on android does not resize pictures when you provide two max dimensions and one dimension is lesser than one provided...

Transition of images in Windows Forms Picture box

I'm new to Windows Forms, in my project, i need to change the image in the picture box at runtime. I'm able to do that with the help of a timer. The picture just gets changed. Is it possible to do some transitions when image changes, for example fade in, fade out, blur etc.. If possible could some one please let me know how to do it. I searched in net but in vain.Thanks in advance.
Varun
Simply take new code file and paste below code in it
an original answer for the similar question, answer taken from another question
Answer
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
public class BlendPanel : Panel
{
private Image mImg1;
private Image mImg2;
private float mBlend;
public BlendPanel()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
public Image Image1
{
get { return mImg1; }
set { mImg1 = value; Invalidate(); }
}
public Image Image2
{
get { return mImg2; }
set { mImg2 = value; Invalidate(); }
}
public float Blend
{
get { return mBlend; }
set { mBlend = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
if (mImg1 == null || mImg2 == null)
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(0, 0, this.Width, this.Height));
else
{
Rectangle rc = new Rectangle(0, 0, this.Width, this.Height);
ColorMatrix cm = new ColorMatrix();
ImageAttributes ia = new ImageAttributes();
cm.Matrix33 = mBlend;
ia.SetColorMatrix(cm);
e.Graphics.DrawImage(mImg2, rc, 0, 0, mImg2.Width, mImg2.Height, GraphicsUnit.Pixel, ia);
cm.Matrix33 = 1F - mBlend;
ia.SetColorMatrix(cm);
e.Graphics.DrawImage(mImg1, rc, 0, 0, mImg1.Width, mImg1.Height, GraphicsUnit.Pixel, ia);
}
base.OnPaint(e);
}
}
Build your project. You can now drop a BlendPanel from the top of the toolbox onto your form. Here's a sample program that uses it:
private float mBlend;
private int mDir = 1;
public int count = 0;
public Bitmap[] pictures;
public void myPhoto()
{
pictures = new Bitmap[9];
pictures[0] = new Bitmap(#"Library Images\cf3.jpg");
pictures[1] = new Bitmap(#"Library Images\cf4.jpg");
pictures[2] = new Bitmap(#"Library Images\l1.JPG");
pictures[3] = new Bitmap(#"Library Images\l2.JPG");
pictures[4] = new Bitmap(#"Library Images\l3.JPG");
pictures[5] = new Bitmap(#"Library Images\l4.JPG");
pictures[6] = new Bitmap(#"Library Images\l5.JPG");
pictures[7] = new Bitmap(#"Library Images\l6.JPG");
pictures[8] = new Bitmap(#"Library Images\l7.JPG");
timer1.Interval = 50; //time of transition
timer1.Tick += BlendTick;
try
{
blendPanel1.Image1 = pictures[count];
blendPanel1.Image2 = pictures[++count];
}
catch
{
}
timer1.Enabled = true;
}
private void BlendTick(object sender, EventArgs e)
{
mBlend += mDir * 0.02F;
if (mBlend > 1)
{
mBlend = 0.0F;
if ((count + 1) < pictures.Length)
{
blendPanel1.Image1 = pictures[count];
blendPanel1.Image2 = pictures[++count];
}
else
{
blendPanel1.Image1 = pictures[count];
blendPanel1.Image2 = pictures[0];
count = 0;
}
}
blendPanel1.Blend = mBlend;
}
You'll need to modify the new Bitmap(#"yourimagePath"); calls. Build and run. You should see the displayed image smoothly morph from your first image to your second image without any flickering.
I hope it helps for other...
There is no built-in support for such effects, but you can implement them. I'd suggest to write a custom control that renders the image and have a method for fade-swap, fade itself can be reached with alpha-blending drawing with .NET Graphics class.
However, Graphics class isn't very fast, I don't recommend to use this technique for big images. If you need some fancy UI with hw-accelerated effects, take a look at WPF.
Blend effects are easy to get going by using the ColorMatrix class. There's a good example available in my answer in this thread.
A simple way to get a blur is to resize the image, making it smaller, then redraw it back, making it larger. The Graphics.InterpolationMode property affects the type of blur you'll get.
Those are quicky do-it-yourself solutions. Any decent graphics library has these kind of operations built-in. You probably want something free, check out ImageMagick.NET
To put it simply, not without external (3rd-party) libraries.

Resources