I am attempting to make a slider bar that randomly changes the color of several parts of the users interface when the user slides the bar from one side to the other. I have a piece of code that already works but I know it's not as efficient as it could be. I have 3 of the same layout modifiers as below:
private void getLayout2(){
int color = 0;
final Random randColor2 = new Random();
int control = randColor2.nextInt(4);
switch(control){
case 0: color = getResources().getColor(R.color.White);
Log.i(TAG, "color is white");
break;
case 1: color = getResources().getColor(R.color.Red);
Log.i(TAG, "color is red");
break;
case 2: color = getResources().getColor(R.color.Yellow);
Log.i(TAG, "color is yellow");
break;
case 3: color = getResources().getColor(R.color.Blue);
Log.i(TAG, "color is blue");
break;
}
Layout2.setBackgroundColor(color);
return;
}
What I would like to do is change all of the layout backgrounds in the same piece of code but I am not sure how to do that as there is only one color variable and I don't want all the colors to be the same at any given time. Currently I am just calling multiple versions of this method for each layout in the "onProgressChanged" method of the slider listener. Can this be done in a single method with this scheme?
There are a number of options. You can have your function return a the color and set it your main routine, or you can pass the layout as a parameter to your function. An example of the latter follows. Since this is a function, the color variable is recreated every time it is called, so no need to worry that it will be the same when you call the function a different time. Try it and see.
private void setRandomBackgroundColor(View layout){
int color = 0;
final Random randColor = new Random();
int control = randColor.nextInt(4);
switch(control) {
case 0:
color = getResources().getColor(R.color.White);
Log.i(TAG, "color is white");
break;
case 1:
color = getResources().getColor(R.color.Red);
Log.i(TAG, "color is red");
break;
case 2:
color = getResources().getColor(R.color.Yellow);
Log.i(TAG, "color is yellow");
break;
case 3:
color = getResources().getColor(R.color.Blue);
Log.i(TAG, "color is blue");
break;
}
layout.setBackgroundColor(color);
return;
}
Related
I am a little bit of a novice Android developer but I am working on a project to improve memory efficiency in our app's handling of images.
Right now, we have some code for rotating an image based on the Exif data to ensure that it's right side up. I'd like to do the same thing but in Glide, but I can't find any documentation on that... or even documentation on reading Exif data.
I have to imagine this is a fairly common use case! I'd like to take the following code and reduce it to a straightforward Glide method.
Here's what we have now:
final Matrix bitmapMatrix = new Matrix();
int widthMultiplier = 1;
int heightMultiplier = 1;
try {
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(bo.toByteArray()));
final Collection<ExifIFD0Directory> exifIFD0Directories = metadata.getDirectoriesOfType(ExifIFD0Directory.class);
if (exifIFD0Directories != null) {
for (ExifIFD0Directory d : exifIFD0Directories) {
if (d.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
try {
final int exifOrientation = d.getInt(ExifIFD0Directory.TAG_ORIENTATION);
switch (exifOrientation) {
case 1:
break; // top left
case 2:
heightMultiplier = -1;
break; // top right
case 3:
bitmapMatrix.postRotate(180);
break; // bottom right
case 4:
bitmapMatrix.postRotate(180);
heightMultiplier = -1;
break; // bottom left
case 5:
bitmapMatrix.postRotate(90);
heightMultiplier = -1;
break; // left top
case 6:
bitmapMatrix.postRotate(90);
break; // right top
case 7:
bitmapMatrix.postRotate(270);
heightMultiplier = -1;
break; // right bottom
case 8:
bitmapMatrix.postRotate(270);
break; // left bottom
default:
break; // Unknown
}
break;
} catch (MetadataException e) {
handleException(e, subscriber, uri, inputStream, mFinalPath, fromGallery);
return;
}
}
}
}
} catch (ImageProcessingException | IOException e) {
handleException(e, subscriber, uri, inputStream, mFinalPath, fromGallery);
return;
}
Any ideas are appreciated.
From some additional resource, it sounds as if Glide actually handles this automatically.
I want to change the bitmap that contains an image whenever user tap on the screen. i.e. the default image is shadow1, now what i want is that when user touched on screen then this image changed to shadow2, then again if user touched then shadow3, then on next touch the image again comes as shadow1 and it goes on and on and on. so basically there are three images and i want that when ever user touched on screen then image changes with each tap.
Following is the code that i tried but it is still not working as expected i.e. the image changes from shadow1 to shadow2 but then not changes to shadow3 or shadow1 even if i touched many times.
public void Touched(float x, float y)
{
boom = false;
try{
switch (bird.GetState()) {
case 0:
distance = 0;
bird.SetState(1);
flapped = true;
Bitmap workingBitmap = BitmapFactory.decodeResource(gameLogic.Resources(), R.drawable.shadow1);
bitmapBird = workingBitmap.copy(Bitmap.Config.ARGB_8888, false);
if (bitmapBird==workingBitmap)
{
}
riseCounter = 0;
pipeValues.clear();
//SoundManager.playSound(2, 1);
break;
case 1:
{
riseCounter = 0;
flapped = true;
t = 3;
Bitmap workingBitmappp = BitmapFactory.decodeResource(gameLogic.Resources(), R.drawable.shadow2);
bitmapBird = workingBitmappp.copy(Bitmap.Config.ARGB_8888, false);
//SoundManager.playSound(2, 1);
}
break;
case 2:
{
riseCounter = 0;
flapped = true;
t = 0;
}
break;
default:
Bitmap workingBitma = BitmapFactory.decodeResource(gameLogic.Resources(), R.drawable.shadow3);
bitmapBird = workingBitma.copy(Bitmap.Config.ARGB_8888, false);
break;
}
} catch(Exception e){}
}
I think there should be a for loop or while loop in 'case 1' and whenever user tap then image changes. Please help me with this.
You can simply use an int value to keep track of the image displayed as;
First Initialize a int at class level;
int num = 0;
then you can use it as;
if(num == 0){
loadFirstImage();
num++;
}
else if(num == 1)
{
loadSecondImage();
num++;
}
else if(num == 2){
loadThirdImage();
num = 0 ;
}
I think that you need to change the state of the bird in your second case statement.
First iteration will set the state to 1, from there, the only case statement you can hit is case 1: because you never change it.
So you need something like
case 1:
bird.SetState(2);
//....
Hope that helps
I have this code from RatingBar android - custom draw runtime
It worked before which I used to change the color of a graphic on my rating control:
vthf.rating.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
//--
float touchPositionX = event.getX();
float width = vthf.rating.getWidth();
float starsf = (touchPositionX / width);
starsf = starsf * param_final__data.score_max;
int starsint = (int) Math.round(starsf);
byte starsbyte = (byte) starsint;
param_final__data.score_cur = starsbyte;
starsf = starsint;
vthf.rating.setRating(starsf);
//--
int color = Color.BLACK;
switch (starsbyte % 4) {
case 0: color = Color.BLUE; break; // 4 stars
case 3: color = Color.GREEN; break;
case 2: color = Color.YELLOW; break;
case 1: color = Color.RED; break;
}
final LayerDrawable layerDrawable = (LayerDrawable) vthf.rating.getProgressDrawable();
Drawable myWrap = layerDrawable.getDrawable(2);
//--
//
//--
myWrap = DrawableCompat.wrap(myWrap);
//myWrap = myWrap.mutate();
//--
// myWrapMutate.setColorFilter(color, PorterDuff.Mode.SRC_IN);
// DrawableCompat.setTintList(myWrap, ColorStateList.valueOf(color));
//--
DrawableCompat.setTint(myWrap, color);
//--
vthf.rating.invalidate();
}
else
if (event.getAction() == MotionEvent.ACTION_DOWN) {
param_final__view.setPressed(true);
}
else
if (event.getAction() == MotionEvent.ACTION_CANCEL) {
param_final__view.setPressed(false);
}
return true;
}
});
I believe it stopped working after I upgraded from Android Studio 1.5.1 and all support libraries (not sure what version) - I am not 100% sure though since I am no sure I dsicovered the problem immediate or if it had been here longer.
I am tesing on Huawei P6 Android 4.4.2
My gradle is looking like his:
compileSdkVersion 23
buildToolsVersion '23'
dependencies {
compile 'com.android.support:support-v4:+'
compile 'com.google.android.gms:play-services:+'
compile 'com.android.support:appcompat-v7:+'
}
My manifest has this
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="17"
/>
This is my best lead on why the code is no longer working - but I am open to all kinds of suggestions if I am missing something obvious that could cause this unrelated to API versions.
---Note---
This code appears to tint the graphic slightly darker:
final LayerDrawable layerDrawable = (LayerDrawable) vthf.rating.getProgressDrawable();
Drawable myWrap = layerDrawable.getDrawable(2);
myWrap = DrawableCompat.wrap(myWrap);
DrawableCompat.setTint(myWrap, color);
This code has no effect:
final LayerDrawable layerDrawable = (LayerDrawable) vthf.rating.getProgressDrawable();
Drawable myWrap = layerDrawable.getDrawable(2);
DrawableCompat.setTint(myWrap, color);
Not sure what to make of the above. Maybe the problem is caused by something else that I do not understand. If the graphic is darkened, one would think it is kinda working... But it is the exact same darkening no matter he color - a least as far as my eye can tell.
I use something like this to set the Color. Might work here as well, all objects that inherrit from View should be able to do this. This case uses ContextCompat to get to the color, but there are more ways than this to get the color you want.
View view = (findViewById(R.id.text_view_location));
view.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.wantedColor));
Something in AppCompat 23.3 breaks my previous solution. Anyway, you can get your rating bar back to work just by avoiding DrawableCompat#Wrap:
ratingBarB.setOnTouchListener(new View.OnTouchListener() {
private int lastColoredProgress = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
int progress = ratingBarB.getProgress();
if (progress != lastColoredProgress) {
lastColoredProgress = progress;
int color;
switch (lastColoredProgress) {
case 0:
case 1:
color = Color.RED;
break;
case 2:
case 3:
color = Color.YELLOW;
break;
case 4:
default:
color = Color.GREEN;
break;
}
final Drawable drawable = ratingBarB.getProgressDrawable();
if (drawable instanceof LayerDrawable) { // Lollipop and newer
final LayerDrawable layerDrawable = (LayerDrawable) drawable;
DrawableCompat.setTint(layerDrawable.getDrawable(2), color);
} else {
DrawableCompat.setTint(drawable, color);
}
}
return false;
}
});
When you wrap your Drawable with DrawableCompat, a new DrawableWrapper is created. You need to set the new drawable to your component.
In your code, you need to add somethink like this (just after setTint) :
layerDrawable.setCompoundDrawablesWithIntrinsicBounds(myWrap, null, null, null);
I want to generate/randomize a color and then I want second one that is close to the generated one.
This is how I generate the colors ftm:
Paint colors = new Paint();
int red = ran.nextInt(256-100)+100;
int green = ran.nextInt(256-100)+100;
int blue = ran.nextInt(256-100)+100;
colors.setARGB(255, red, green, blue);
and later the 2nd color I generate like this:
switch (ran.nextInt(3)) {
case 0:
red = red - (40 - level);
break;
case 1:
green = green - (40 - level);
break;
default:
blue = blue - (40-level);
break;
}
The problem is that it works in some cases and sometimes it can give me a 2nd color that is off by miles.
Is there another, better and easier way to generate these colors?
br
You need to create a real random number between 0 and 3:
Random ran = new Random();
int max = 3;
int min = 0;
int randomNum = ran.nextInt((max - min) + 1) + min;
switch (randomNum ) {
case 0:
red = red - (40 - level);
break;
case 1:
green = green - (40 - level);
break;
default:
blue = blue - (40-level);
break;
}
You could use java.awt.Color.brighter() and Color.darker().
I have a Options Activity, where I select the color using a RadioButton. By default, the White color is set android:checked="true". Now when I reach to my Canvas,I need to change the Paint color dynamically depending on which RadioButton was selected.
Here's the code that I have tried:
String radioButtonSelected = "";
switch (checkedRadioButton) {
case R.id.CheckRed : radioButtonSelected = "Red";
break;
case R.id.CheckBlue : radioButtonSelected = "Blue";
break;
case R.id.CheckWhite : radioButtonSelected = "White";
break;
}
Intent i = new Intent(HandwritingRecognitionOptionTab.this,HandwritingRecognitionCanvas.class);
i.putExtra("setColor",radioButtonSelected);
//startActivity(i); // because I don't want to start the activity immediately after this
In the class for Canvas:
Bundle getValue = getIntent().getExtras();
drawColor = getValue.getString("setColor");
if(drawColor.equals("White"))
intColor = 1;
if(drawColor.equals("Red"))
intColor = 2;
if(drawColor.equals("Blue"))
intColor = 3;
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.WHITE);
if(intColor == 1)
mPaint.setColor(Color.WHITE);
if(intColor == 2)
mPaint.setColor(Color.RED);
if(intColor == 3)
mPaint.setColor(Color.BLUE);
But I get a NullPointerException whenever the Activity for Canvas is started. It is important to note that by default White should be the color. Also, this doesn't store it persistently right? Should I look into SharedPreferences for this ?
After reading through your comments it looks like that you are not starting the other activity using the given Intent and hence the NullPointerException as the Bundle wont be containg the same string in the next activity.
You can opt out for the following options:
1> Shared Prefrences (As highlighted by you)
2> Some DB entry.
3> Some file storage
4> Singleton pattern
but for me the best one would have been a shared prefrence. You might also want to have a look at this link for a detail