How to implement a vertical ProgressBar as an Activity Background - java

I ran into this app concept by Oleg Frolov on Dribble.
The implementation seems pretty basic, with a horizontal ScrollView and a button which triggers the reveal animation.
I want to know :-
How to implement the vertical ProgressBar as the background of the
countdown activity
How to sync the progress of the ProgressBar, and the TextView's text change with the Chronometer/ System clock.

this project show you how to implement such a progress bar.

that is very simple to do with a custom drawable, there's no need to use libraries.
below is an UNTESTED example on how to do it.
public class CustomDrawable extends Drawable {
private final int color1;
private final Paint paint;
float level;
public CustomDrawable(int color1, int color2) {
this.color1 = color1;
paint = new Paint();
paint.setColor(color2);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
#Override public void draw(Canvas canvas) {
canvas.drawColor(color1);
level = getLevel() / 100f;
canvas.drawRect(
0,
canvas.getHeight() * level, // tweak this line if not drawing properly
canvas.getWidth(),
canvas.getHeight(), paint);
}
#Override public void setAlpha(int alpha) {
}
#Override public void setColorFilter(ColorFilter colorFilter) {
}
#Override public int getOpacity() {
return 0;
}
}
on the background view just use this drawable like:
background.setBackground(new CustomDrawable(color1, color2));
then to update the value u call
background.getBackground().setLevel(... between 0-100...);

Related

Trying to populate the screen with objects

it seems I have a problem understanding classes. It would be great if someone could help.
I'm trying to populate my Smartphone screen (android) with 3 circles of different color.
My problem is that by using the code below I only get one (blue) circle.
I considered that the Problem is that the y-value isn't set correctly and the 3 circles are hiding each other (so that only the blue one is visible). But when I log the y-value of the 3 circle objects, the y-values seem to be correct (200,500,800)
Whats am I doing wrong?
Thanks for your help in advance.
public class MainActivity extends Activity {
public Circle circleR;
public Circle circleG;
public Circle circleB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circleR = new Circle(this, 200, 255, 0, 0);
setContentView(circleR);
circleG = new Circle(this, 500, 0, 255, 0);
setContentView(circleG);
circleB = new Circle(this, 800, 0, 0, 255);
setContentView(circleB);
}
}
public class Circle extends View {
public Paint paint;
public int y;
public Circle(Context context,int y, int r, int g, int b){
super(context);
paint=new Paint();
paint.setColor(Color.rgb(r,g,b));
this.y=y;
}
#Override
protected void onDraw(Canvas canvas){
canvas.drawCircle(30, this.y,30, paint);
}
}
The problem lies in setting the content view multiple times. Only the view set as last (the one with a blue circle) will be visible. If you want multiple circles to be visible at the same time you should draw them on one canvas localized inside one view. I rearranged your code so that it does what you wanted:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CirclesView circlesView = new CirclesView(this);
setContentView(circlesView);
}
}
public class CirclesView extends View {
public Circle circleR;
public Circle circleG;
public Circle circleB;
public CirclesView(Context context) {
super(context);
circleR = new Circle(200, 255, 0, 0);
circleG = new Circle(500, 0, 255, 0);
circleB = new Circle(800, 0, 0, 255);
}
#Override
protected void onDraw(Canvas canvas){
circleR.draw(canvas);
circleG.draw(canvas);
circleB.draw(canvas);
}
}
public class Circle {
public Paint paint;
public int y;
public Circle(int y, int r, int g, int b) {
paint = new Paint();
paint.setColor(Color.rgb(r,g,b));
this.y=y;
}
public void draw(Canvas canvas) {
canvas.drawCircle(30, this.y,30, paint);
}
}
Circle knows how to draw itself on a canvas which will be provided to it by a view.

I want to return true when my sprite is touched

i want to return true to my method touch, when the sprite is touched (also with the finger) how can I make?
public class SkipButton extends RectangleButton
{
protected TextureAtlas atlasTexture;
protected Sprite sprite;
protected SpriteBatch batch ;
public SkipButton(Vector2 coordinates, float width, float height)
{
super(coordinates, width, height);
atlasTexture = Assets.manager.get(Constants.INTERFACE_ATLAS_PATH,
TextureAtlas.class);
sprite = new Sprite(atlasTexture.findRegion("skip_big"));
}
#Override
public void draw(SpriteBatch batch)
{
sprite.draw(batch);
}
public boolean touch()
{
...........
}
Libgdx has a great Button class which has included a boolean isPressed() which will do what you want. You can still make a public method that returns the result of isPressed if you want your button to be private.
atlasTexture = Assets.manager.get(Constants.INTERFACE_ATLAS_PATH,
TextureAtlas.class);
Drawable drawable = new TextureRegionDrawable(atlasTexture.findRegion("skip_big"));
button = new Button(drawable);
stage.addActor(button);
public boolean touch() {
return button.isPressed();
}

JavaFX - Resize Canvas when screen is resized

I'm working on the GUI of my level editor that I built in JavaFX, and I want to be able to resize the canvas object to the new split pane dimensions. It seems that everything I've tried has failed. This includes passing the pane object in and using its width directly, using window size listeners and binding the width and height property to that of the split pane. Any ideas? This is what it looks like before a resize:
And after a resize:
Does anybody have any ideas? The code for the class is pretty extensive, but the code for the resizing will be included here:
public Canvas canvas;
public String tabTitle;
public VBox layout;
public GraphicsContext g;
public Core core;
public CanvasTab(Core core, String tabTitle){
this.core = core;
this.canvas = new Canvas(core.scene.getWidth() - 70, core.scene.getHeight() - 70);
layout = VBoxBuilder.create().spacing(0).padding(new Insets(10, 10, 10, 10)).children(canvas).build();
this.g = canvas.getGraphicsContext2D();
g.setFill(Color.BLACK);
g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
HBox.setHgrow(layout, Priority.ALWAYS);
this.setContent(layout);
this.setText(tabTitle);
canvas.widthProperty().bind(layout.widthProperty().subtract(20));
canvas.heightProperty().bind(layout.heightProperty().subtract(20));
}
public CanvasTab(Canvas canvas){
this.canvas = canvas;
}
As James_D pointed out, you need to redraw the content of your canvas when resizing. This can be done by adding a listener to your canvas' width and height property as follows:
InvalidationListener listener = new InvalidationListener(){
#Override
public void invalidated(Observable o) {
redraw();
}
});
canvas.widthProperty().addListener(listener);
canvas.heightProperty().addListener(listener);
or in Java 8 using functional interfaces:
canvas.widthProperty().addListener(observable -> redraw());
canvas.heightProperty().addListener(observable -> redraw());
where redraw() is your own method which would look like this for your example (drawing a black rectangle:
private void redraw() {
g.setFill(Color.BLACK);
g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
}
To make a JavaFx canvas resizable all that needs to be done is override the min/pref/max methods. Make it resizable and implement the resize method.
With this method no width/height listeners are necessary to trigger a redraw. It is also no longer necessary to bind the size of the width and height to the container.
public class ResizableCanvas extends Canvas {
#Override
public double minHeight(double width)
{
return 64;
}
#Override
public double maxHeight(double width)
{
return 1000;
}
#Override
public double prefHeight(double width)
{
return minHeight(width);
}
#Override
public double minWidth(double height)
{
return 0;
}
#Override
public double maxWidth(double height)
{
return 10000;
}
#Override
public boolean isResizable()
{
return true;
}
#Override
public void resize(double width, double height)
{
super.setWidth(width);
super.setHeight(height);
paint();
}
Note that the resize method cannot simply call Node.resize(width,height), because the standard implementation is effectivele empty.

Invalidate() not refreshing screen

I want to make it so that pressing the screen moves my rectangle. The listener gives output to console but it doesn't invalidate the screen.
public class DrawView extends View{
Paint paint = new Paint();
static int x = 20;
static int y = 20;
public DrawView(Context context){
super(context);
paint.setColor(Color.GREEN);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawRect(x,y,100,100,paint);
}
public void OTListener(){
setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View DrawView, MotionEvent e){
x = 100;
y = 100;
invalidate();
return false;
}
});
}
}
Try this. It should work if it is the top view in your view hierarchy.
You'll have to check out event.getAction() if you want to do more advanced stuff in onTouchEvent()...
public class DrawView extends View {
Paint paintRect = new Paint();
Paint paintClear = new Paint();
private Point touch = new Point();
public DrawView(Context context){
super(context);
paintClear.setColor(Color.BLACK);
paintRect.setColor(Color.GREEN);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawPaint(paintClear);
canvas.drawRect(touch.x-50,touch.y-50,touch.x+50,touch.y+50,paintRect);
}
private void touch(int x, int y) {
touch.set(x,y);
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
touch((int)event.getX(), (int)event.getY());
return true;
}
}
Using invalidate() in another method doesn't work. You need to use postinvalidate() if you want to refresh activity from another method.

Android Canvas weird shifting

I have a problem I was trying to solve for almost 2 days. (It ended up by switching to OpenGL :D)
Anyway... I have Canvas and I am trying to do a simple snake game. Just for this problem imagine our snake is made up from 5x5 pixels rectangles, he is leaving the trail (no clearing) and moving to the right from 0, 50 position... here is the code:
public class Snake extends AnimationWallpaper {
#Override
public Engine onCreateEngine() {
return new SnakeEngine();
}
class SnakeEngine extends AnimationEngine {
int i = 0;
Paint paint = new Paint();
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// By default we don't get touch events, so enable them.
setTouchEventsEnabled(true);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep, int xPixelOffset,
int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
}
#Override
public Bundle onCommand(String action, int x, int y, int z,
Bundle extras, boolean resultRequested) {
if ("android.wallpaper.tap".equals(action)) {
}
return super.onCommand(action, x, y, z, extras, resultRequested);
}
#Override
protected void drawFrame() {
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
draw(c);
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
}
void draw(Canvas c) {
//c.save();
//c.drawColor(0xff000000);
paint.setAntiAlias(true);
// paint the fill
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
c.drawRect(i*5, 50, (i+1)*5, 55, paint);
//c.restore();
}
#Override
protected void iteration() {
i++;
super.iteration();
}
}
}
And here is output:
And that is not all, when it draws its kinda shifting... meaning what you see is shifted to the right side so it doesnt actualy stand in the same place...
If you have any idea why is it behave like that, please tell me!
In canvas, there's a reusability functionality which practically just add new drawings to whatever is in the canvas, hence if you are drawing 1 square at the time, the next time you will have whatever u had before +1, if you don't want that, and you want to fully manipulate every single draw from scratch, just add this line of code before to start drawing
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
It will clear anything you had in the previous state of the canvas, and you can start again drawing whatever you want...
Hope It Helps!
Regards!

Categories

Resources