Android Wear Watch Face Development Colors - java

I am trying to develop watch faces, and I was able to add the time, date, and other information and position the text. I had trouble with style, mostly color. I have one red text, and another white text. After going to Ambient Mode and turning back to interactive mode, the color is either white or gray depending on the code below. I can only get it to return to one color.
SimpleWatchFaceService.java
package com.me.me.androidwearweather;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.support.wearable.watchface.CanvasWatchFaceService;
import android.support.wearable.watchface.WatchFaceStyle;
import android.view.SurfaceHolder;
import java.util.concurrent.TimeUnit;
public class SimpleWatchFaceService extends CanvasWatchFaceService {
#Override
public Engine onCreateEngine() {
return new SimpleEngine();
}
private class SimpleEngine extends CanvasWatchFaceService.Engine {
private final long TICK_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(1);
private Handler timeTick;
private SimpleWatchFace watchFace;
#Override
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
setWatchFaceStyle(new WatchFaceStyle.Builder(SimpleWatchFaceService.this)
.setCardPeekMode(WatchFaceStyle.PEEK_MODE_SHORT)
.setAmbientPeekMode(WatchFaceStyle.AMBIENT_PEEK_MODE_HIDDEN)
.setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
.setShowSystemUiTime(false)
.build());
timeTick = new Handler(Looper.myLooper());
startTimerIfNecessary();
watchFace = SimpleWatchFace.newInstance(SimpleWatchFaceService.this);
}
private void startTimerIfNecessary() {
timeTick.removeCallbacks(timeRunnable);
if (isVisible() && !isInAmbientMode()) {
timeTick.post(timeRunnable);
}
}
private final Runnable timeRunnable = new Runnable() {
#Override
public void run() {
onSecondTick();
if (isVisible() && !isInAmbientMode()) {
timeTick.postDelayed(this, TICK_PERIOD_MILLIS);
}
}
};
private void onSecondTick() {
invalidateIfNecessary();
}
private void invalidateIfNecessary() {
if (isVisible() && !isInAmbientMode()) {
invalidate();
}
}
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
startTimerIfNecessary();
}
#Override
public void onDraw(Canvas canvas, Rect bounds) {
super.onDraw(canvas, bounds);
watchFace.draw(canvas, bounds);
}
#Override
public void onAmbientModeChanged(boolean inAmbientMode) {
super.onAmbientModeChanged(inAmbientMode);
watchFace.setAntiAlias(!inAmbientMode);
watchFace.setColor(inAmbientMode ? Color.GRAY : Color.WHITE);
// THIS IS WERE I THINK THE PROBLEM IS I tried the method on top and bottom of this comment
// if(inAmbientMode){
// watchFace.setColor(Color.GRAY);
// }
invalidate();
}
#Override
public void onTimeTick() {
super.onTimeTick();
invalidate();
}
#Override
public void onDestroy() {
timeTick.removeCallbacks(timeRunnable);
super.onDestroy();
}
}
}
SimpleWatchFace.java
package com.me.me.androidwearweather;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.format.Time;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class SimpleWatchFace {
private final Paint timePaint;
private final Paint datePaint;
private final Time time;
public static SimpleWatchFace newInstance(Context context) {
Paint timePaint = new Paint();
timePaint.setColor(Color.RED);
timePaint.setTextSize(context.getResources().getDimension(R.dimen.time_size));
timePaint.setAntiAlias(true);
Paint datePaint = new Paint();
datePaint.setColor(Color.WHITE);
datePaint.setTextSize(context.getResources().getDimension(R.dimen.date_size));
datePaint.setAntiAlias(true);
return new SimpleWatchFace(timePaint, datePaint, new Time());
}
SimpleWatchFace(Paint timePaint, Paint datePaint, Time time) {
this.timePaint = timePaint;
this.datePaint = datePaint;
this.time = time;
}
public void draw(Canvas canvas, Rect bounds) {
time.setToNow();
canvas.drawColor(Color.BLACK);
Calendar cal = Calendar.getInstance();
SimpleDateFormat twelvehour = new SimpleDateFormat("h");
SimpleDateFormat ampm = new SimpleDateFormat("a");
String TimeAmPmNoSec = String.format("%2s:%02d %2s", twelvehour.format(cal.getTime()), time.minute, ampm.format(cal.getTime()));
float timeXOffset = computeXOffset(TimeAmPmNoSec, timePaint, bounds);
float timeYOffset = computeTimeYOffset(TimeAmPmNoSec, timePaint, bounds);
canvas.drawText(TimeAmPmNoSec, timeXOffset, timeYOffset, timePaint);
SimpleDateFormat month_date = new SimpleDateFormat("MMM");
SimpleDateFormat day_text = new SimpleDateFormat("E");
String DateNew = String.format("%s | %s %02d", day_text.format(cal.getTime()), month_date.format(cal.getTime()), time.monthDay);
float dateXOffset = computeXOffset(DateNew, datePaint, bounds);
float dateYOffset = computeDateYOffset(DateNew, datePaint);
canvas.drawText(DateNew, dateXOffset, timeYOffset + dateYOffset, datePaint);
}
private float computeXOffset(String text, Paint paint, Rect watchBounds) {
float centerX = watchBounds.exactCenterX();
float timeLength = paint.measureText(text);
return centerX - (timeLength / 2.0f);
}
private float computeTimeYOffset(String timeText, Paint timePaint, Rect watchBounds) {
float centerY = watchBounds.exactCenterY();
Rect textBounds = new Rect();
timePaint.getTextBounds(timeText, 0, timeText.length(), textBounds);
int textHeight = textBounds.height();
return centerY + (textHeight / 2.0f) - 50f;
}
private float computeDateYOffset(String dateText, Paint datePaint) {
Rect textBounds = new Rect();
datePaint.getTextBounds(dateText, 0, dateText.length(), textBounds);
return textBounds.height() + 25f;
}
public void setAntiAlias(boolean antiAlias) {
timePaint.setAntiAlias(antiAlias);
datePaint.setAntiAlias(antiAlias);
}
public void setColor(int color) {
timePaint.setColor(color);
datePaint.setColor(color);
}
}
I was also wondering if it is possible to style a text with more than one font and color.

EDIT 2: Alright, you could just instantiate a new watch face each time the mode is changed (Java will automatically garbage collect the old one, so no worries on memory) OR, I personally would do this.
Add two new functions in your SimpleWatchFace class to replace your setColor function
public void setTimeColor(int color) {
timePaint.setColor(color);
}
public void setDateColor(int color) {
datePaint.setColor(color);
}
then change your function to be this
#Override
public void onAmbientModeChanged(boolean inAmbientMode) {
super.onAmbientModeChanged(inAmbientMode);
watchFace.setAntiAlias(!inAmbientMode);
if(inAmbientMode)
{
watchFace.setTimeColor(Color.BLACK);
watchFace.setDateColor(Color.GREY);
}
else
{
watchFace.setTimeColor(Color.RED);
watchFace.setDateColor(Color.WHITE);
}
}
When the watch is put into Ambient Mode the screen turns itself black and white (or black and grey as you're experiencing)
Note: In low-bit ambient mode, the system does not reliably render the
colors in the image
from The Android Webpage

Related

I am making an app and I require to use the interface Parcelable but facing issues and not sure how to implement it

I am new to coding and to java and android. I am making an app that has multiple canvas views (where a person can draw lines with their finger) in multiple fragments (requested to be like this). I have managed to get the fragments to work and to draw lines on each canvas. Next, I want to be able to save the lines drawn by the user when the user goes to a different fragment or closes the app and when the user comes back to a fragment, the drawing for that fragment will still be there, and can continue editing it by adding more lines or clear it by hitting Clear, the same should happen for other fragments that should have their respective drawings.
I was previously told about the interface Parcelable and have made some steps to implement it but I am finding it hard to understand what I am doing and having trouble reading in an ArrayList. The error is stating that it is expecting ClassLoader but being provided with an ArrayList (I hope in the right place), and that's if I make the getter static but that creates an error: Non-static field 'paths' cannot be referenced from a static context in the getter in the PaintView class (this controls the drawing). I get a similar static context message for the readArrayList method in the FingerPath class. Once this is figured out, I will need to find out how to bring the relevant, saved drawing back to the canvas when the fragment is opened which I am not sure how, I think when the Bundle isn't equal to null but not sure.
I'll show the code below (right now it is on a test app)
FingerPath class
import android.graphics.Path;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
public class FingerPath implements Parcelable {
public int color;
public boolean emboss;
public boolean blur;
public int strokeWidth;
public Path path;
public FingerPath(int color, boolean emboss, boolean blur, int strokeWidth, Path path) {
this.color = color;
this.emboss = emboss;
this.blur = blur;
this.strokeWidth = strokeWidth;
this.path = path;
}
protected FingerPath(Parcel in) {
color = in.readInt();
emboss = in.readByte() != 0;
blur = in.readByte() != 0;
strokeWidth = in.readInt();
//line below causing me issues
path = in.readArrayList(PaintView.getPaths());
}
public static final Creator<FingerPath> CREATOR = new Creator<FingerPath>() {
#Override
public FingerPath createFromParcel(Parcel in) {
return new FingerPath(in);
}
#Override
public FingerPath[] newArray(int size) {
return new FingerPath[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(color);
parcel.writeByte((byte) (emboss ? 1 : 0));
parcel.writeByte((byte) (blur ? 1 : 0));
parcel.writeInt(strokeWidth);
//parcel.writeParcelableArray(PaintView.getPaths(), 0);
}
}
PaintView
Controls what happens when the user starts drawing
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class PaintView extends View {
public static int BRUSH_SIZE = 10;
public static final int DEFAULT_COLOR = Color.WHITE;
public static int DEFAULT_BG_COLOR = Color.GRAY;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private ArrayList<FingerPath> paths = new ArrayList<>();
private int currentColor;
private int backgroundColor = DEFAULT_BG_COLOR;
private int strokeWidth;
private boolean emboss;
private boolean blur;
private MaskFilter mEmboss;
private MaskFilter mBlur;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
public PaintView(Context context) {
this(context, null);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mEmboss = new EmbossMaskFilter(new float[] {1, 1, 1}, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(5, BlurMaskFilter.Blur.NORMAL);
}
//the getter in question
public ArrayList getPaths() {
return paths;
}
public void init(DisplayMetrics metrics) {
int height = metrics.heightPixels;
int width = metrics.widthPixels;
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
}
public void normal() {
emboss = false;
blur = false;
}
public void clear() {
backgroundColor = DEFAULT_BG_COLOR;
paths.clear();
normal();
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mCanvas.drawColor(backgroundColor);
for (FingerPath fp: paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.emboss)
mPaint.setMaskFilter(mEmboss);
else if (fp.blur)
mPaint.setMaskFilter(mBlur);
mCanvas.drawPath(fp.path, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y) {
mPath = new Path();
FingerPath fp = new FingerPath(currentColor, emboss, blur, strokeWidth, mPath);
paths.add(fp);
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x-mX);
float dy = Math.abs(y-mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP :
touchUp();
invalidate();
break;
}
return true;
}
}
Here's an example of a fragment
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class LineLHwFragment extends Fragment {
private PaintView paintView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_line_l_hw, container, false);
paintView = v.findViewById(R.id.lineLPaintView);
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
paintView.init(metrics);
setHasOptionsMenu(true);
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.normal:
paintView.normal();
return true;
case R.id.clear:
paintView.clear();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("line test", paintView.getPaths());
}
}

How do you show where on the board the user has pressed for a mobile sudoku game?

I am making a sudoku game in java - Intellij. I want to show the user where they have pressed and I do not know how to do so.
If you need the whole file its on the github:
https://github.com/SamirSydykov03/Sudoku-Varients-for-mobile-phones
Here is my Game.java
import com.example.sudokuvarients.normalsudoku9x9.SudokuGrid.GameGrid;
public class Game {
private static Game instance;
private GameGrid grid = null;
private int selectedX = -1;
private int selectedY = -1;
private Game(){}
public static Game getInstance(){
if(instance == null){
instance = new Game();
}
return instance;
}
public void createGrid(Context context){
int[][] Sudoku = SudokuGenerator.getInstance().generateGrid();
Sudoku = SudokuGenerator.getInstance().removal(Sudoku);
grid = new GameGrid(context);
grid.setGrid(Sudoku);
}
public GameGrid getGrid(){
return grid;
}
public void setSelectedPos(int x, int y){
setSelectedItem();
selectedX = x;
selectedY = y;
}
public void setSelectedItem(){
grid.getItem(-1,-1);
}
public void setNumber(int number){
if(selectedY != -1 && selectedX != -1){
grid.setItem(selectedX,selectedY,number);
}
grid.checkGame();
}
Here is my BaseSudokoCell.java
package com.example.sudokuvarients.normalsudoku9x9.SudokuGrid;
import android.content.Context;
import android.view.View;
public class BaseSudokuCell extends View {
private boolean modify = true;
private int value;
private boolean selected;
public BaseSudokuCell(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
public void setNotModify(){
modify = false;
}
public void setInitialValue(int value){
this.value = value;
invalidate();
}
public void setValue(int value){
if(modify){
this.value = value;
}
invalidate();
}
public boolean getSelect(){
return selected;
}
public int getValue(){
return value;
}
}
Here is my SudokuCell.java - It does draw a tile, but it does not hide and it is drawn in all the cells. It does not do anything when clicked.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
public class SudokuCell extends BaseSudokuCell{
private Paint mPaint;
public SudokuCell(Context context){
super(context);
mPaint =new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawNumber(canvas);
drawLines(canvas);
drawRectangle(canvas);
}
private void drawLines(Canvas canvas) {
mPaint.setColor(Color.MAGENTA);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
canvas.drawRect(0,0,getWidth(), getHeight(), mPaint);
}
private void drawNumber(Canvas canvas) {
mPaint.setColor(Color.CYAN);
mPaint.setTextSize(60);
mPaint.setStyle(Paint.Style.FILL);
Rect bounds = new Rect();
mPaint.getTextBounds(String.valueOf(getValue()), 0, String.valueOf(getValue()).length(), bounds);
if (getValue() != 0) {
canvas.drawText(String.valueOf(getValue()), (getWidth() - bounds.width()) / 2, (getHeight() + bounds.height()) / 2, mPaint);
}
}
private void drawRectangle(Canvas canvas){
Rect ourRect = new Rect();
ourRect.set(0,0,canvas.getWidth()-5,canvas.getHeight()-5);
Paint grey = new Paint();
grey.setColor(Color.GRAY);
grey.setStyle(Paint.Style.FILL);
canvas.drawRect(ourRect,grey);
}
}

Text In-screen Implementation in java-libGDX

I have some trouble with implementing a feature to show and use the player's username. I'm making a crossplatform app between windows and android where I'm trying to showcase the player's name as soon as they start typing and can press enter to proceed or press the Level Selection-button to proceed to the next screen. Every time I press ''Enter'' though, it crashes. Also, doesn't it display or take in the player's name. I know the code is not optimal as I made multiple tables for example but I was hoping somebody could tell me where I made my mistake so it would maybe work. Thanks in advance!
This is the code:
package com.paladinzzz.game.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.viewport.FillViewport;
import com.paladinzzz.game.CrossplatformApp;
import com.paladinzzz.game.util.Constants;
import com.paladinzzz.game.audio.MusicHandler;
import static com.badlogic.gdx.Gdx.input;
import static com.paladinzzz.game.screens.MenuScreen.musicHandler;
public class LoginScreen implements Screen {
private CrossplatformApp game;
private Stage stage;
private ImageButton backButton, playButton;
private Texture backTexture, playTexture, background;
private Drawable drawableBack, drawablePlay;
private OrthographicCamera camera;
BitmapFont font = new BitmapFont();
int[] x = new int[255];
public static boolean inPlayscreen = false;
public static String playername = "";
private boolean isConverted = false;
private Table table, table2;
public LoginScreen(CrossplatformApp game) {
this.game = game;
this.camera = new OrthographicCamera();
this.stage = new Stage(new FillViewport(Constants.WIDTH, Constants.HEIGHT, camera));
this.playTexture = new Texture("Screens/LoginScreen/LvlSelection.png");
this.backTexture = new Texture("Screens/BackButton.png");
this.background = new Texture("Screens/LoginScreen/loginscreen.png");
}
#Override
public void show() {
//Give the texture of the backButton to a new ImageButton
drawableBack = new TextureRegionDrawable(new TextureRegion(backTexture));
backButton = new ImageButton(drawableBack);
backButton.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new MenuScreen(game));
MenuScreen.musicHandler.stopMusic();
}
});
//Give the texture of the playButton to a new ImageButton
drawablePlay = new TextureRegionDrawable(new TextureRegion(playTexture));
playButton = new ImageButton(drawablePlay);
playButton.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
game.setScreen(new LevelScreen(game));
inPlayscreen = true;
}
});
//Elements can be added here to the stage
input.setInputProcessor(stage);
//A table gets made with the button which leads to the level selection screen
table = new Table();
table.bottom();
table.setFillParent(true);
table.add(playButton).padBottom(40);
stage.addActor(table);
//A table gets made with the button which leads back to the main menu
table2 = new Table();
table2.bottom();
table2.setFillParent(true);
table2.add(backButton).padBottom(13).padRight(640);
table2.row();
stage.addActor((table2));
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(Gdx.input.isKeyJustPressed(Input.Keys.ENTER)){
game.setScreen(new LevelScreen(game));
inPlayscreen = true;
if (!isConverted){
playername = playername.substring(0, 1).toUpperCase() + playername.substring(1, playername.length()).toLowerCase();
isConverted = true;
}
}
game.batch.begin();
//A possibility gets made to insert the name of the player
game.batch.draw(background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
for (int i : x) {
if (input.isKeyJustPressed(i)){
if (i != 62 && i != 67 && i!= 66) {
playername += Input.Keys.toString(i).toLowerCase();
} else if (i == 67 & playername.length() > 0){
playername = playername.substring(0, playername.length() - 1).toLowerCase();
} else {
playername += " ";
}
}
}
font.draw(game.batch, playername, 0, 0);
game.batch.end();
stage.draw();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
stage.dispose();
}
}
This is how the ''LoginScreen'' looks like:
GameScreen
This is the error message:
Exception in thread "LWJGL Application"
java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.substring(String.java:1963)
at com.paladinzzz.game.screens.LoginScreen.render(LoginScreen.java:108)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.paladinzzz.game.CrossplatformApp.render(CrossplatformApp.java:30)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:225)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)
Debugging with breakpoint:
The crash solution is for this line:
playername = playername.substring(0, 1).toUpperCase() + playername.substring(1, playername.length()).toLowerCase();
your second substring needs to use
playername.length()-1

Libgdx- How to scale animation

I want to In the click the screen then Slide ya animated change the screen.
this code has been only the change the image but it has not animated . I want to change the image on the click of screen is animated and then change.. Only change the image is code is bellow but how to animated is not know???
package com.check;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.utils.ArrayMap;
public class TutorialUI implements Screen, ApplicationListener{
private static final String TEXTURE_PATH = "data/animvs-logo.png";
private AssetManager assetManager;
private SpriteBatch batch;
private Stage stage;
private boolean tuchb=true;
private ArrayMap<Integer, Item> items;
private ArrayMap<Integer, Item> itemsDisplayed;
private Skin uiSkin;
private Table scrollTable;
private TextField textSearch;
private String searchLastCriteria;
TextButton button;
TextButtonStyle textButtonStyle;
TextureAtlas buttonAtlas;
BitmapFont font;
Texture logo,logo1,logo2;
Window window;
#Override
public void create() {
batch = new SpriteBatch();
stage = new Stage();
items = new ArrayMap<Integer, Item>();
itemsDisplayed = new ArrayMap<Integer, Item>();
Gdx.input.setInputProcessor(this.stage);
assetManager = new AssetManager();
assetManager.load("data/animvs-logo.png", Texture.class);
assetManager.load("data/uiskin.atlas", TextureAtlas.class);
assetManager.finishLoading();
uiSkin = new Skin(Gdx.files.internal("data/uiskin.json"), assetManager.get("data/uiskin.atlas", TextureAtlas.class));
scrollTable = new Table();
scrollTable.setCenterPosition(250, 400);
criaItens(10);
window = new Window("Animvs - UI / ScrollPane Tutorial", uiSkin);
window.setBounds(0, 100, 500, 500);
textSearch = new TextField("", uiSkin);
textSearch.addListener(new InputListener() {
public boolean keyDown(InputEvent event, int keycode) {
if (keycode == Keys.ENTER)
rearrangeTable();
return super.keyDown(event, keycode);
}
});
stage.addActor(scrollTable);
}
int tuch=1;
#Override
public void render() {
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 60f));
Gdx.gl.glClearColor(0, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
stage.draw();
batch.end();
if(Gdx.input.justTouched()){
if(tuch<9 && tuchb){
tuch=tuch+1;
rearrangeTable();
}
}
}
#Override
public void resize(int width, int height) {
batch.getProjectionMatrix().setToOrtho2D(0f, 0f, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// stage.setViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
rearrangeTable();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
// Don't forget to free unmanaged objects:
batch.dispose();
uiSkin.dispose();
stage.dispose();
}
private final void criaItens(int total) {
items.clear();
itemsDisplayed.clear();
for (int i = 0; i <total ; i++) { // imagearr
Color novaCor = new Color(MathUtils.random(0.5f), MathUtils.random(0.5f), MathUtils.random(0.5f), 1f);
items.put(i, new Item(i, "Item " + i, assetManager.get(TEXTURE_PATH, Texture.class), novaCor, uiSkin));
// items.put(i, new Item(i, "Item " + i,imagearr.get(i), novaCor, uiSkin));
}
}
private final void rearrangeTable() {
scrollTable.clear();
computeDisplayedItems(textSearch.getText());
for (int i = 0; i < tuch; i++) {
addImage(tuch);
}
}
public final void addImage(int indice) {
scrollTable.add(itemsDisplayed.getValueAt(indice).getImage())
.minHeight(500)
.minWidth(500)
.center().expand();
}
private final void computeDisplayedItems(String searchCriteria) {
if ((searchCriteria == null && searchLastCriteria == null) || searchCriteria.equals(searchLastCriteria)) {
if (items.size != itemsDisplayed.size) {
itemsDisplayed.clear();
itemsDisplayed.putAll(items);
}
return;
}
itemsDisplayed.clear();
if (searchCriteria == null || searchCriteria.isEmpty()) {
itemsDisplayed.putAll(items);
return;
}
for (int i = 0; i < items.size; i++) {
if (items.getValueAt(i).getDescription().getText().toString().contains(searchCriteria))
itemsDisplayed.put(items.getKeyAt(i), items.getValueAt(i));
}
searchLastCriteria = searchCriteria;
}
#Override
public void render(float delta) {
// TODO Auto-generated method stub
}
#Override
public void show() {
// TODO Auto-generated method stub
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
}
An other class......
package com.check;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
public final class Item {
private final class ImageClick extends ClickListener {
private Item item;
public ImageClick(Item item) {
this.item = item;
}
public void clicked(InputEvent event, float x, float y) {
if(item.getId()==0){
// game.setScreen(new PowerScreen(game));
}
Gdx.app.log("SELECTED ITEM", "ID: " + item.getId() + " Description: " + item.getDescription().getText());
}
}
private int id;
private Label description;
private Image image;
private Color color;
public final int getId() {
return id;
}
public final Label getDescription() {
return description;
}
public final Image getImage() {
return image;
}
public final Color getColor() {
return color;
}
public Item(int index, String description, Texture texture, Color color, Skin skin) {
this.id = index;
this.description = new Label(description, skin);
this.image = new Image(texture);
this.color = color;
image.setColor(color);
image.addListener(new ImageClick(this));
}
}
See the answer for this link of this Question https://github.com/krustnic/HorizontalSlidingPane

generating random circles in android

Im trying to make a simple app that draws random circles when one button is pushed, and clears them all from the screen when another is pushed. Currently When i start the app on an emulator for some reason it starts with an automatically generated circle, then If I attempt to push the button to generate another circle the app crashes and I get a NullPointerException at my
c.drawcircle(b.getX(), b.getY(), b.getR(), p)
method.
Heres what I currently have:
Main:
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class Bubbles extends Activity implements OnClickListener
{
Button b1,b2;
drawView dv;
LinearLayout frame;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bubbles);
dv = new drawView(getApplicationContext());
frame = (LinearLayout)findViewById(R.id.LinearLayout2);
b1 = (Button)findViewById(R.id.BubbleButton);
b1.setOnClickListener(this);
b2 = (Button)findViewById(R.id.ClearButton);
b2.setOnClickListener(this);
frame.addView(dv);
}
#Override
public void onClick(View v)
{
if(v==b1)
{
dv.onDraw(null);
}
if(v==b2)
{
dv.clear();
}
v.postInvalidate();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.bubbles, menu);
return true;
}
}
drawView:
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class drawView extends View
{
ArrayList<Bubble> bList = new ArrayList<Bubble>();
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
public drawView(Context con)
{
super(con);
}
public void onDraw(Canvas c)
{
Bubble b = new Bubble();
p.setColor(b.getColor());
p.setStyle(Paint.Style.FILL);
bList.add(b);
c.drawCircle(b.getX(), b.getY(), b.getR(), p);
}
public void clear()
{
bList.clear();
}
}
Im using an arrayList in this class to store all the bubbles I make and then clear the arrayList using the clear button.
Here is the Bubble class I made that goes with it:
Bubble:
import android.graphics.Color;
public class Bubble
{
int color;
int y;
int x;
int r;
public Bubble ()
{
color = Color.rgb(rand(0,255), rand(0,255), rand(0,255));
r = rand(0,255);
x =rand(0,255);
y = rand(0,255);
}
public int getColor() {
return color;
}
public int getY() {
return y;
}
public int getX() {
return x;
}
public int getR() {
return r;
}
/******************************rand()*****************************/
public int rand(int a, int b)
{
return((int)((b-a+1)*Math.random() + a));
}
}
Thanks for any input, This is my first time messing with graphics so Im not 100% sure why this is happening.
you pass null to your method onDraw here:
dv.onDraw(null);
I guess you would want to pass a Canvas there.
In this method then your Canvas will point to null since you passed null as the param:
public void onDraw(Canvas c) {
Bubble b = new Bubble();
p.setColor(b.getColor());
p.setStyle(Paint.Style.FILL);
bList.add(b);
c.drawCircle(b.getX(), b.getY(), b.getR(), p); // c == null here!
}
==> NPE
as for your random method try this
Random rng = new Random();
in your field declarations.
then use. rng.nextInt(255);
color = Color.rgb(rng.nextInt(255), rng.nextInt(255), rng.nextInt(255));
as for your circles: firstly you need an update method(if you want any movement)
secondly you should be using a surfaceView to draw, and thirdly you should use a
copyOnWriteArrayList, because your button may be modifying the list while its iterating over it, and copyonwritearraylist is perfect for that. here: my gift to you.
CLASS 1
import java.util.Random;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
public class GrowCircle {
float x, y;int radius;
Paint myp = new Paint();
int colr,colg,colb;
int redvar=1;
int bluevar=5;
int greenvar=2;
int tripper=10;
int change=2;
Random rand = new Random();
public GrowCircle(float x, float y){
this.x=x;
this.y=y;
this.radius=2;
this.colr=rand.nextInt(254)+1;
this.colg=rand.nextInt(254)+1;
this.colb=rand.nextInt(254)+1;
}
public void update(){
radius+=4;
tripper+=change;
if(tripper<=1||tripper>=15){
change=-change;
}
Random col = new Random();
myp.setColor(Color.argb(255,colr,colg,colb));
colr+=redvar;
colg+=greenvar;
colb+=bluevar;
if(colr<=5||colr>=250){
redvar=-redvar;
}
if(colg<=5||colg>=250){
greenvar=-greenvar;
}
if(colb<=5||colb>=250){
bluevar=-bluevar;
}
}
public void drawThis(Canvas canvas){
myp.setStrokeWidth(tripper);
myp.setStyle(Style.STROKE);
canvas.drawCircle(x, y, radius, myp);
}
}
CLASS2
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import com.gmaninc.acidrain2.R;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.service.wallpaper.WallpaperService;
import android.service.wallpaper.WallpaperService.Engine;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.View.OnTouchListener;
public class LiveWallpaperService extends WallpaperService {
CopyOnWriteArrayList<GrowCircle> gc = new CopyOnWriteArrayList<GrowCircle>();
private final Handler mHandler = new Handler();
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public Engine onCreateEngine() {
return new CubeEngine();
}
class CubeEngine extends Engine {
private final Paint mPaint = new Paint();
private float mOffset;
private float mTouchX = -1;
private float mTouchY = -1;
private long mStartTime;
private float mCenterX;
private float mCenterY;
private final Runnable mDrawCube = new Runnable() {
public void run() {
drawFrame();
}
};
private boolean mVisible;
CubeEngine() {
// Create a Paint to draw the lines for our cube
final Paint paint = mPaint;
paint.setColor(0xffffffff);
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.STROKE);
mStartTime = SystemClock.elapsedRealtime();
}
#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 onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mDrawCube);
}
#Override
public void onVisibilityChanged(boolean visible) {
mVisible = visible;
if (visible) {
drawFrame();
} else {
mHandler.removeCallbacks(mDrawCube);
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
// store the center of the surface, so we can draw the cube in the right spot
mCenterX = width/2.0f;
mCenterY = height/2.0f;
for(GrowCircle circ:gc){
circ.update();
}
drawFrame();
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
mVisible = false;
mHandler.removeCallbacks(mDrawCube);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xStep, float yStep, int xPixels, int yPixels) {
mOffset = xOffset;
drawFrame();
}
/*
* Store the position of the touch event so we can use it for drawing later
*/
#Override
public void onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mTouchX = event.getX();
mTouchY = event.getY();
} else {
mTouchX = -1;
mTouchY = -1;
}
float tx = event.getX();
float ty= event.getY();
gc.add(new GrowCircle(tx,ty));
super.onTouchEvent(event);
}
/*
* Draw one frame of the animation. This method gets called repeatedly
* by posting a delayed Runnable. You can do any drawing you want in
* here. This example draws a wireframe cube.
*/
void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
// draw something
drawCircs(c);
for(GrowCircle circ:gc){
if(circ.radius>350){
gc.remove(circ);
}
circ.update();
circ.drawThis(c);
}
drawTouchPoint(c);
}
} finally {
if (c != null) holder.unlockCanvasAndPost(c);
}
// Reschedule the next redraw
mHandler.removeCallbacks(mDrawCube);
if (mVisible) {
mHandler.postDelayed(mDrawCube, 1000 / 25);
}
}
/*
* Draw a wireframe cube by drawing 12 3 dimensional lines between
* adjacent corners of the cube
*/
void drawCircs(Canvas c) {
c.save();
c.translate(mCenterX, mCenterY);
c.drawColor(0xff000000);
c.restore();
}
/*
* Draw a circle around the current touch point, if any.
*/
void drawTouchPoint(Canvas c) {
if (mTouchX >=0 && mTouchY >= 0) {
c.drawCircle(mTouchX, mTouchY, 80, mPaint);
}
}
}
}
MANIFEST
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gmaninc.acidrain2"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<uses-feature
android:name="android.software.live_wallpaper"
android:required="true" >
</uses-feature>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service
android:name="LiveWallpaperService"
android:enabled="true"
android:label="Acid Rain 2"
android:permission="android.permission.BIND_WALLPAPER" >
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" >
</action>
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/mywallpaper" >
</meta-data>
</service>
</application>
</manifest>
this is a livewallpaper that creates circles onTouch... feel free to play around with it, you should find what you need in here....
NOTE: you may need to change the package name in the manifest to get it to run!

Categories