-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Android Image that has a complex background (i.e. with rounded corners) cannot animate opacity correctly. #1223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I could not find a way to correctly animate the opacity of an android.widget.ImageView which has a background with rounded corners. The opacity is animated, but the rounded corners disappear for some mysterious Android reason. However, here is a very simple workaround which should resolve the problem. Replace the Image widget with any kind of Layout widget, let's say StackLayout. Then bind the style.backgroundImage property to your view model property. In the CSS for the widget add background-size: contain; in order to center the image. In this way, the actual image and the rounded corners will be drawn together and the opacity animation should run. Exampe: <StackLayout loaded="imageLoaded" style.backgroundImage="{{ ProfilePic100 }}" row="0" col="0" class="avatar-list-avatar" visibility="{{ ProfilePic100 ? 'visible' : 'collapsed' }}" /> .avatar-list-avatar{
opacity: 0;
font-size:35;
height: 40;
width: 40;
border-radius: 20;
margin-left: 16;
horizontal-align: center;
vertical-align: center;
background-size: contain;
} This should do the trick. The bottomline is that if you want to animate the opacity of an image with rounded corners background, replace it with any kind of layout component and set its backgroundImage instead. |
@hamorphis - I can't get this to work, what version did you try this on? I even simplified the StackLayout a bit to make sure it wasn't the visibility, but no luck.
|
I will see what's going on tomorrow. |
I'll check again but I think I had it work briefly by just setting backgroundImage and not style. property. I did numerous things and it worked but it also raises another question on how to trigger the animation each time the image comes into view. On some apps I've seen the opacity animation will run as they load in and also as you scroll back up the listview. If you have some thoughts on that let me know. Thanks |
I am currently working on a fix. |
….e. with rounded corners) cannot animate opacity.
Resolved Issue #1223: Android views which have complex backgrounds (i…
Forget about the StackLayout. You will be able to use the Image after we release version 1.6. I merged a fix into the master branch. The fix will be released with version 1.6. As for playing the animation each time the image comes into view, here is a way to achieve this. Imagine that your ListView looks something like this: <ListView items="{{ redditItems }}" isScrolling="{{ isScrolling }}" itemTap="listViewItemTap" loadMoreItems="listViewLoadMoreItems"
itemLoading="listViewItemLoading">
<ListView.itemTemplate>
<!-- Binding in template property of an component will use the bindingContext provided by the component. -->
<GridLayout columns="auto, *, auto" rows="auto, 25">
<Image src="{{ thumbnailImage }}" class="thumbnail" rowSpan="2" loaded="imageLoaded" tag="thumbnail"/>
<Label text="{{ title || 'Downloading...' }}" textWrap="true" class="title" col="1" colSpan="2" minHeight="50" />
<Label text="{{ author ? 'by ' + author : '' }}" class="author" col="1" row="1" />
<Label text="{{ num_comments ? num_comments + ' comments' : '' }}" class="comments" col="2" row="1" />
</GridLayout>
<!-- End of tempplate. -->
</ListView.itemTemplate>
</ListView> function imageLoaded(args) {
console.log(args.object + " loaded for the first time.");
args.object.opacity = 0;
args.object.animate({ opacity: 1, duration: 10000 });
}
exports.imageLoaded = imageLoaded;
function listViewItemLoading(args) {
var gridLayout = args.view;
gridLayout._eachChildView(function (childView) {
if (childView["tag"] === "thumbnail" && childView.isLoaded) {
console.log(args.object + " coming into view.");
childView.opacity = 0;
childView.animate({ opacity: 1, duration: 10000 });
return false;
}
return true;
});
}
exports.listViewItemLoading = listViewItemLoading; .thumbnail {
opacity: 0;
width: 72;
height: 72;
margin: 3;
vertical-align: top;
border-radius: 36;
} Here is the app I tested with: https://www.dropbox.com/s/nql8hqaavl5vxba/VSDevApp.zip?dl=0 It uses with our latest tns-core-modules from the master branch. |
I'll try this with the master branch tomorrow. Thanks for the animation code above too! 👍 |
Great. Let me know if this works for you so we can close this issue in case it does. |
@hamorphis would updating the core modules be all I need to do? If so, the images still just appear after the 'duration' has ended. I'm downloading your sample now to try it on a couple devices to see if it works. |
@hamorphis - just installed the .apk from your sample and it's the same end result. The images just pop into view after the duration. |
@hamorphis - I've tried running it on a Droid Turbo 2 (5.1.1) and in GenyMotion emulator with 5.0.0 What android version did you try it on? |
Here is what I found which is very weird:
I tested with all kinds of widgets, not just the image, and in version 5 on Android nothing works like on the other versions. What the hell. Versions 4 and 6 work just fine which just kills me. I will see whether I can do something about version 5, but currently I don't know what to "fix" or "hack" so it works on Android 5. |
Another interesting finding. The background completely disappears if I set opacity (i.e. on a button click for example) on any view on Android 5.x. It is not the animation itself that is the problem. I created a separate issue: #1240 |
This magic setting seems to fix all visual glitches related to opacity, animations and backgrounds on all API Levels: if (view.android) {
view.android.setLayerType(android.view.View.LAYER_TYPE_HARDWARE, null);
} where view is the misbehaving widget. Can you try this. Alternatively, you can also try setting LAYER_TYPE_SOFTWARE instead of LAYER_TYPE_HARDWARE. Call this method in your loaded event handler just before you spin off the animation. Let me know if this fixes the issue. |
I'll try it later this weekend. Thanks. @vakrilov knows all about that setting :), I had a bug with border radius On Sat, Dec 12, 2015, 7:00 AM Rossen Hristov notifications@github.com
|
… Use this to fix visual glitches: view.android.setLayerType(android.view.View.LAYER_TYPE_HARDWARE, null);
That is a mysterious setting. Only the Android guys know what it does on what API levels. It is not our bug, its theirs. So we would prefer people to set this thing in their projects, we are afraid to hard-code such stuff in the core modules since we might break a lot of people. What I mean is that if you were not using NativeScript at all and you we writing pure Android app in Java, you would encounter exactly the same issues, so I don't believe it in our hands to fix their bugs or mention them in our docs. We can't make a huge switch statement with the cartesian product of all possible API Levels, LAYER_TYPES and possible bugs :) :) That woulds be up to the individual projects that people develop. I can only add a line of code to set it to HARDWARE in case a complex border is being drawn and the API Level is > 18. I hope I will not break anyone else though. |
|
…null); for complex backgrounds on API Level > 18. (Resolves #1223)
@hamorphis - the layerType does fix it. Thanks for figuring that out. One small issue - if it's not related we can open another issue. Since I want the image to run the animation with the itemLoading event, the animation runs but some images in the list will do the animation and then just "pop" in afterwards. More of a "flash" than a pop I suppose. My list is a small array right now for testing, maybe 20 user records and the API returns just random items right now so I'll have duplicates. So that might be part of the issue, let me know if you need more info. |
A little more info, it seems that this second flash effect is once the animation finishes. I'm trying to find out if it's because of some CSS setting and a conflict with the animation or an event. If I find anything else I'll be sure to note it. |
It also seems consistent to trigger once the scroll comes to a stop. |
Can you please open a separate issue and attach a small dummy sample project that clearly demonstrates the glitches you observe. I will run it and see whether it is something under our control or not. Thanks in advance. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Android views which have complex backgrounds (i.e. with rounded corners) cannot animate opacity. The ObjectAnimator will not suffice for such cases and has to be replaced by a ValueAnimator.
The text was updated successfully, but these errors were encountered: