I have a GLSurfaceView with a renderer assigned to it. On this view, I draw images which seem to be offset to the left compared to where I have requested that they be drawn on it. This problem has only arisen since I switched from Canvas-based rendering, which rendered the images in their correct positions, to OpenGL 1.0 rendering, which doesn't.
I have read through my code and have found absolutely nothing that could be causing this. What frustrates me is that I know there is nothing wrong with the positions I set using my code, but the problem still persists.
Now, here's the best part of it all. When I pause the application by pressing the home button, and then restart the application through the task manager, the positions are fixed and are exactly how they should be, which leads me to believe that the problem isn't with the positions I set using my code, but how I've set up my surface view. I've checked the dimensions in the onSurfaceChanged() parameters only to find that they are always as they should be, which leaves me even more confused.
Does anyone have any idea what could be causing this problem?
After much digging through my project, I discovered I was setting positions based on the dimensions of the GLSurfaceView before onSurfaceChanged had been called in the onSurfaceCreated method, therefore the width/height of the view at this point was 0 which affected the positions of my objects on the screen.
I feel really stupid now.
Related
I've been trying to solve my problem for a long time now. However, I'm at a loss. The problem is this:
I have a Custom Android View that I render 10 rectangles on(kind of
like a bar chart all the same length, different color)
When updating one of the rectangles with different opacity, it
doesn't change. So I clear the Canvas. But this causes a flicker,
not all the time, but sometimes
What I've tried doing:
Render everything to an offscreen bitmap, then blting it, this still
doesn't solve my issue
Use a SurfaceView and render in another thread
A combination of 1 and 2
In the end, I think the problem is that the background gets erased, but I don't want it to erase. However, I can never get the new "pixels" to show up. I also tried experimenting with different transfer modes like SRC, SRC_ATOP, when I tried number 1, it helps, but does not get rid of the problem.
Does anyone have any guidance on what could be going wrong? Or any other possible solutions?
I have finally figured it out. I don't have to clear the back ground, just temporarily change the paint mode to SRC.
context.paint.setStyle(Paint.Style.FILL);
context.paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
context.canvas.drawPath(context.path, context.paint);
context.paint.setXfermode(null);
I have encountered the nasty Android SurfaceView behavior:
When you leave an Activity with SurfaceView and quickly go back, the previous content of SurfaceView doesn't disappear and is displayed under the new one.
See the example project that reproduces the problem, please.
https://github.com/t-artikov/surface-view-bug
I have found that this is an Android bug, which was fixed on Android P
https://issuetracker.google.com/issues/72624889
But I need to get it to work on earlier OS versions.
Will be glad to any ideas how to solve the issue. Maybe someone has already encountered it and knows a workaround.
Note: This problem wouldn't occur on an API 22 device. I used the Pixel 2 API 26, as the OP did, in order to reproduce it.
It appears that, under this condition, the SurfaceView saves its current contents to some sort of hidden intermediate surface, at certain times (like when a transition begins). The condition can't be corrected by replacing the SurfaceView, or by adjusting the background drawables of any ancestor views.
Your onDrawFrame() is clearing the buffer with a transparent color, which is letting this "intermediate surface" show through. If you don't need the transparency, you could just clear it to solid white:
GLES20.glClearColor(1, 1, 1, 1);
EDIT
I found myself coming back to this question, as it is a very troublesome bug. Since you need to keep the transparency, it turns out you can add this to SecondActivity, to avoid the problem:
#Override
protected void onStart()
{
overridePendingTransition(0,0);
super.onStart();
}
I also tried disabling hardware acceleration, but no luck there.
I've been fiddling around with RenderBlur on an image for my login screen, i've gotten everything to work with a runnable() and a delay to blur the image immediately, however i'm trying to make it a slow blur while the username and password fields come into view.
I've had a bit of a look around (could be looking in the wrong places) but I haven't found anything related to what i'm after. I've attempted to use a while loop and have a blurradius value increment with a delay afterwards and send to the blurBitmap class method, but it either still blurs it immediately (meaning I probably messed something up somewhere and will most likely keep trying with this method until a better solution is found).. or it crashes.
Does anyone know if, in the first place this is possible with RenderScript? And if so, what should I be searching for.
Thanks for any help you can provide.
Resources: https://futurestud.io/blog/how-to-use-the-renderscript-support-library-with-gradle-based-android-projects
You can do this with RenderScript, though how you are doing it now doesn't sound like a good idea. Look into using a custom Animator which you can then run a RS blur against the image. Using Animator will be more flexible in the long run and automatically ties in with the view system rather than requiring you to handle View or Activity state explicitly.
The approach #JasonWihardja outlined will also work, but again I would suggest doing this in an Animator or similar mechanism.
Blurring an image repeatedly might cause some performance issues with your app.
Here's what you could do:
Arrange 2 images (1 for the clear image and the other for the
maximum blur version) so that the blur image is placed exactly on
top of the clear image. The easiest way would be placing 2 ImageViews in a FrameLayout
To achieve the "slow" blur effect, initially set the blur image's alpha to 0.
Then, using one of the view, issue a postDelayed event to slowly increase the blur image's alpha to 255.
I know this is quite the same question as partial-invalidation-in-custom-android-view-with-hardware-acceleration but I thought I will explain my problem more detailled and hope someone will have an answer on how to solve the problem.
I wrote a simple TicTacToe app which was working fine on the emulator. But wasn't working on the device since I found out it was working as expected on the device when I disabled hardware acceleration.
All the fields are drawn with Canvas.drawBitmap(), also the "empty" fields with an empty white image. The lines are drawn with Canvas.drawLine()
I'm using partial invalidation with invalidate(Rect) because I want to redraw only the area which was choosen to set a cross/circle with the according image using again Canvas.drawBitmap(). But then the whole area is invalidated, means I see the whole area/screen is gray (the white images and lines disappeared) and only the image for the cross/circle is set in the choosen area.
When I print out the invalidated field rect with Canvas.getClipBounds() in the method onDraw(), with hardware acceleration it is the whole area (example "0,0,320,407") and without hardware acceleration the same rect which I invalidated with invalidate(Rect) (e.g. "106,135,106,135").
At the moment as workaround I redraw all the fields whith the according image and lines. How can I prevent to have the whole area invalidated with hardware acceleration?
If this matters: I'm using Android version 4.1.2 on Samsung Galaxy Young Duos S6312.
Regards
Sandro
I have post my answer in your given link. To understand the problem , you should know the difference between software rendering and hardware rendering. That's really a big topic which I won't cover here. I think the best approach is to read the source code(I did the same thing a few days ago). The key question is "what is DisplayList and when it is used"
. Repeat my answer here, the Canvas in onDraw is simply used to rebuild the DisplayList. That doesn't mean everything in your View will be redrawn.
What is the best way to draw circles on a canvas that should have an alpha layer and change sizes? Should I use a View or a Surfaceview? The circles should also be clickable. And it should be smooth transitions when changing color size and position?
Should I put this in a runnable or use invlaidate in onDraw?
I would prefer that something like this also worked smoothly in low-end devices.
Any suggestions? I'm new to this kind of animations in Android.
If you are constantly drawing and taking user input at the same time, I would use a SurfaceView. However, if the only draw changes you plan on making to the circles happen when you touch them, then a simple View onDraw() override would probably do the trick. In the end it will just depend on what all is going on.
The point of the SurfaceView is to have that separate thread for drawing. If what you're doing could be in any way considered "game-like," then go for a SurfaceView; otherwise, stick with a View.
I say this because I'm currently working on a project with constant drawing using a View. The shapes that I'm drawing respond to touch and you can scroll through the View while it is still invalidating over and over. All this with a View and it still runs just fine on lower-end devices (I've only gone back to GingerBread, though).
Good luck!
I should also mention that in the project drawing in a View, almost everything has various alpha values and what not and runs fine.