Problem & Question:
I currently have a view pager, with just 2 pages/views inside it, which are next to each other horizontally.
My views are custom ones which draw a two-color gradient and an image over the top of it at a low opacity/alpha value.
I'm finding that when I swipe across the screen to move from the first view/page to the second or vice-versa, the images are getting squashed. How can I stop this from happening, and draw them normally?
Example:
The left image shows the first view that is visible, pre-swipe; the right image shows the two views, midway through swipe.
Code:
I have a Drawable variable I set earlier, overlayImage, that I have not done anything to other than setting opacity.
#Override
protected void onDraw(Canvas canvas) {
p.setShader(new LinearGradient(0, 0, 0, getHeight(), startColor, endColor, Shader.TileMode.MIRROR));
canvas.drawPaint(p);
//Pretty sure the mistake is around these two next lines
overlayImage.setBounds(canvas.getClipBounds());
overlayImage.draw(canvas);
}
I actually think it is in your
overlayImage.setBounds(canvas.getClipBounds());
line of code. When you are getting the clip bounds of the left most (swiping in the right most) view, it is getting the size of the viewable area (i.e. the smaller shrinking area) and thus the image is being drawn into that shrinking space.
You probably want to be setting the bounds by the overall size of the view it is being overlayn on, not the clipped bounds. Use instead getHeight() and getWidth() of the canvas and build up your own bounds.
I actually think that you really should setup the overlayImage bounds ONLY ONCE in your setup code. The draw code shouldnt necessarily need to set that up at all, then when the view begins to go off screen the drawing of the overlayImage will naturally move with the rest of the drawing canvas.
I think that you need to make a xml in the drawable-hdpi folder.
Which will contain your shader/linear gradiant.. (for options look here)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient
android:startColor="#474946"
android:endColor="#181818"
android:angle="270"/>
</shape>
And then you can set the xml as background.. which should fix the problem i think.
(If it doesn't work try without the android:shape="rectangle", that might help)
Related
I have a button and I want to make an animation of going down. I made it but the functionality is left at the previous position(like the button moves but if I click on it, it doesn't work, but if I click its previous position it will work)
Animation logbtn = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.logbtnanim);
button.startAnimation(logbtn);
And the animation code is this.
P.S. Parent is the constraint layout.
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate
android:fromYDelta="0"
android:toYDelta="100"
android:duration="1000"/>
</set>
First of all you don't need the AnimatorSet Tag if you only have one animation. This is used if you want to play multiple animations together.
Second you are using TranslateAnimation which does not animate the Buttons property, it only moves the pixels on the screen, so after the animation, Android still thinks the view is at the old position, that is why it is still clickable there.
I suggest doing it in Java code using ViewPropertyAnimator something like :
button.animate().translationY(...f).duration(1000);
Or ObjectAnimator which is a little more flexible since you can also do it in xml.
I'm trying to create a "fill-up" animation on a shape in Android. It should start being completely invisible and then gradually "fill up" from the bottom like this:
What I am specifically trying to animate is a circle such as this one:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#666666"/>
<size
android:width="120dp"
android:height="120dp"/>
</shape>
I have checked out the AlphaAnimation, RotateAnimation, ScaleAnimation and TranslateAnimation (sublasses of Animation) but I can't find a way to use them for this.
Here is how I eventually solved it:
I included this library from github https://github.com/lzyzsd/CircleProgress which contains a circular progress bar (CircleProgress). I added a countdowntimer to gradually increase the "progress" it is displaying
Here is the code:
final CircleProgress circularProgress =(CircleProgress)findViewById(R.id.circleProgress);
//Hides the text and the part of the circle which should not be shown
circularProgress.setUnfinishedColor(Color.parseColor("#00000000"));
circularProgress.setTextColor(Color.parseColor("#00000000"));
//Makes the circle red
circularProgress.setFinishedColor("#FF0000");
final int timeToCountDownMilis = 10000;
circularProgress.setMax(timeToCountDownMilis);
//Initiates and starts the countdowntimer which gradually increases the "progress" in the progress bar
new CountDownTimer(timeToCountDownMilis,70){
onTick(long milisUntilFinished){
circularProgress.setProgress(timeToCountDownMilis-(int)milisUntilFinished);
}
onFinish(){
}
}.start();
Thanks to Stan for pointing me to circular progress bars!
You could dig deep in Animations, like drawPath etc. What I should do in this case is simplier a bit:
-place a full red circle on a screen
-put a View with white bg over it (like a square), covering all the circle
-animate that white square View moving up revealing your circle
You could use a simple transition animation to do it.
That way it gonna looks like a filling animation you want.
Well, my answer was given following images you provide and it covers the target good enough. But if you wish something like a progress bar looking so, you should visit https://github.com/snowdream/awesome-android and check circular progress bar libs there, at least you'll maybe lern how to achieve your goal Or find out its already done.
I've been trying to create a bar chart/ loading bar where the text is half one colour and half one another and have been struggling to come up with a simple way to tackle this. My ideas thus far have revolved around creating both bars in their complete state and then having a pair of 'selective transparency' views which would show the respective halves to create the effect.
I've been unable to find how to do this selective transparency/ opacity view. Is this possible? Is there some other blindingly obvious way to achieve this effect?
Here's a quick drawing of what I'm trying to achieve.
For anyone stumbling across this, I managed to solve this by using setClipBounds. I did it by creating two textviews of the full size, one with a coloured number and transparent background and the second with a white number and coloured background. Then setClipBounds is applied to the coloured textview as follows -
textview.setClipBounds( new Rect(0, originalHeight*(1 - progress), originalWidth, originalHeight);
Here, the variable progress has a value between 0 and 1. The Rect has to be defined relative to the view, not relative to the screen.
This exact setup achieves an effect something like this, but it could easily be changed to a horizontal bar or whatever else is required.
Somehow misinterpreted the question. The best way to achieve this would be to create the images and set as background to an imageview instead of a textview.
You could just use a LinearGradient
With the parameters colors and positions you can indicate the loading progress.
You can use the gradient when you override the onDraw Custom Drawing
I am trying to make a simple app just to understand better how to use Touch events on Android. Right now, my Activity just moves an ImageView to the coordinates of the touch on the screen (the MotionEvent's coordinates). I could manage to do this by applying a simple trick to set the new position of the image to a value that is made of the touch coordinates relative to the position of the image (getX() and getY()). The dx and dy variables are responsible to store this relative values so the touch keeps constant within the image.
Now I want to put 2 ImageViews in the Activity and have only two fixed spots for ImageViews and once the user drags one ImageView over the other ImageView's center, the two images switch places, but to do that correctly I would like to get the real coordinates of the image center. I commented the parts of the code that make it work correctly to show the issue. As you can see in the first picture when the view is created, the Image Coordinates are simply (0, 0), no matter where it is (as long as the initial position is defined as a layout parameter like CENTER_IN_PARENT).
As you can see in the second picture and as far as I observed ImageView's getX() and getY() return the coordinate as if the top-left corner of the image was in the top-left corner of the DISPLAY when the image is located at the top-left corner of the ACTIVITY WINDOW.
I would like to understand why that happens and if anyone knows how to actually get the coordinates of ImageView that can be directly compared to the coordinates of MotionEvent.
Pictures:
FIRST PICTURE
SECOND PICTURE
I still don't know exactly why getX(), getY(), setX(), and setY() do not represent the position of the View on the screen, but I figured out how to get the actual location of the view objects on the screen: getLocationOnScreen(coordinates). Where coordinates is a 2 position int array (int[2]).
For example, to get the real value correspondent to the top-left corner of my ImageView image I simply need to do something like:
int[] img_coordinates = new int[2];
ImageView image = (ImageView) findViewById(R.id.myImage);
image.getLocationOnScreen(img_coordinates);
And then I can actually compare these coordinates with the Touch-event's getRawX and getRawY.
If I want to get the center point of my view I just need to do this:
x_center = (double)img_coordinates[0] + image.getWidth()/2.0;
y_center = (double)img_coordinates[1] + image.getHeight()/2.0;
I hope this helps other people too, it took me a while to find this approach and I am actually not sure if it is the best approach but it does the trick for me.
I have a RelativeLayout with an ImageView and 8 TextView's in it. I want to position labels around this image dynamically. I thought the best approach would be to rotate the image at 45 degree intervals and place a label at each position, however the Image/RelativeLayout doesn't redraw (even if invalidate is called) until the next predetermind onDraw call, and all the TextViews get put in the message queue for positioning after that, so all the TextViews get positioned ontop of each other at the 315 degree mark.
I tried posting a Runnable to the RelativeLayout in a hope it would be added to the message queue after the onDraw call but unfortunately it didn't work and I'm running out of ideas.
My current code is bellow to give an idea of what I'm trying to do:
public void setupMenuText() {
final float scale = getResources().getDisplayMetrics().density;
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos0), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos1), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos2), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos3), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos4), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos5), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos6), (72*scale)+0.5f);
setupMenuItemText((TextView)findViewById(R.id.menu_text_pos7), (72*scale)+0.5f);
}
public void setupMenuItemText(TextView pT, float pY) {
relativeLayout.setRotation(relativeLayout.getRotation()+45);
pT.setText("Some Text");
pT.setRotation(0);
pT.setGravity(Gravity.CENTER_HORIZONTAL);
pT.setX(0);
pT.setY(pY);
}
EDIT: Thanks to JSchools for the answer, wasn't exactly what I needed but pointed me in the right direction and info was accurate.
For anyone else with the same problem, centering the text inside the TextView wont cut it. I manually had to set the size of the TextView to much higher than its intended use so that it would accurately be positioned relative to the image.
You need to set the rotation of each individual TextView. You seem to be rotating the container multiple times, but since all the TextViews are inside the container, and they all have zero rotation relative to the container, they seem stacked. Don't rotate the container at all. You will also need to set the position of the TextViews so that they will be arranged in a circle. Simply rotating them will stick them on top of each other.