I'm currently coding a simple memory game for android and ran into this problem:
I wanted to animate my card (which is an image button) to flip around. This works. What however doesn't work is, the drop shadow assigned to the button through the elevation property. It doesn't display as expected and introduces graphical glitches and small performance issues.
You can have a look at the glitches here:
graphical glitches on the drop shadow
The buttons are defined in my activity_memory.xml file like this:
<!-- ... -->
<ImageButton
android:layout_width="70dp"
android:layout_height="70dp"
android:id="#+id/btn_1_1"
android:layout_column="0"
android:background="#drawable/zelda0"
android:layout_margin="2dp"
android:gravity="center"
android:onClick="button11clicked"
android:elevation="5dp" />
<!-- ... -->
the animation is specified in my drawable/animator flipcardtoback.xml file like this:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Rotate. -->
<objectAnimator
android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:interpolator="#android:interpolator/accelerate_decelerate"
android:duration="1000" />
</set>
The code triggers an animation function which flips the card and halfway through the animation duration it switches the background image of the button from the frontside image to the backside image of the card.
I guess the way I flip the card isn't the problem. It's just the drop shadow which glitches. I don't really know how to fix this, as I've tried to make a new drawable resource forming a drop shadow and assign this to the background property of the button. This however results in the image obviously not being displayed.
Is there any way to fix this so it animates the drop shadow correctly or in a way which is more pleasing to the eye?
Scale down one button and a scale up the reverse. This way the button stays flat and Android has no trouble displaying a shadow.
public static final AccelerateInterpolator
ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
public static final DecelerateInterpolator
DECELERATE_INTERPOLATOR = new DecelerateInterpolator();
...
private void animateFromTo(final Button buttonLeave, final Button buttonArrive) {
buttonArrive.setVisibility(View.INVISIBLE);
buttonLeave.animate()
.setDuration(250)
.scaleY(0)
.setInterpolator(ACCELERATE_INTERPOLATOR)
.setListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
buttonLeave.setVisibility(View.INVISIBLE);
buttonArrive.setScaleY(0);
buttonArrive.setVisibility(View.VISIBLE);
buttonArrive.animate()
.setDuration(250)
.scaleY(1)
.setInterpolator(DECELERATE_INTERPOLATOR)
.setListener(null)
.start();
}
}).start();
}
Related
I have the following problem:
I try to use Glide to add to my ImageButton a background, but if I try it, the image sometime very-very big, little, not in the right place, and often the real ImageButton sticking out from behind.
Like this picture: https://www.kephost.com/image/El2G
So, how can I resize, or place, to the button from behind doesn't look, and the whole picture can see in the upper screen.
My Codes:
.xml
<ImageButton
android:id="#+id/ib1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
.java
Glide.with(MainMenu.this)
.load(R.drawable.updatelogkisfelbontas)
.fitCenter()
.placeholder(R.drawable.updatelogkisfelbontas)
.into(ib1);
}
try this:
Glide.with(MainMenu.this)
.load(R.drawable.updatelogkisfelbontas)
.override(200, 200);
.centerCrop();
.placeholder(R.drawable.updatelogkisfelbontas)
.into(ib1);
}
Preamble
I've been g00gling for half an hour now, and it seems like I'm really missing something important.
Note: I've already tried the solutions for these questions
How to change color of vector drawable path on button click
How to set tint for an image view programmatically in android?
Changing ImageView source
These solutions either recolor ALL ImageView srcs or they don't do anything at all (vector remains black).
My drawable is a vector asset from the material icons directory:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z" />
</vector>
My ImageView:
<ImageView
android:id="#+id/gradeBullet"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="25.5dp"
android:layout_marginTop="25.5dp"
app:srcCompat="#drawable/importantgrade" />
I would like to do this with *Compat, because I'd also like to support earlier APIs (API>17).
My ImageView: ImageView gradeBullet = convertView.findViewById(R.id.gradeBullet);
Try I.
MyAmazingAdapter.java - getChildView(...)
gradeBullet.setColorFilter(ContextCompat.getColor(context, gradeObj.colorId), PorterDuff.Mode.MULTIPLY);
Result: Does nothing.
Try II.
MyAmazingAdapter.java - getChildView(...)
DrawableCompat.setTint(gradeBullet.getDrawable(), ContextCompat.getColor(context, R.color.myColor));
Result: Recolors everything.
Try III.
MyAmazingAdapter.java - getChildView(...)
VectorDrawableCompat drawable = (VectorDrawableCompat) gradeBullet.getDrawable();
drawable.setTint(ContextCompat.getColor(context, gradeObj.colorId));
gradeBullet.setImageDrawable(drawable);
Result: Gives a weird color. (Definitely not what I want, it's closer to the original color)
Try IV.
All the above with a final to the gradeBullet, got the same results.
Some other info
The gradeObj.colorId is different for every childView.
Using shapes and setColor instead of SVG is not what I want.
Currently only tested with API lvl 26
MyAmazingAdapter.java extends BaseExpandableListAdapter
If you'd like more info, just mention it in a comment.
You can try your first method with PorterDuff.Mode.SRC_IN or PorterDuff.Mode.SRC_ATOP instead of PorterDuff.Mode.MULTIPLY.
PorterDuff.mode
Hope this helps.
I am using a built-in theme for my Android app:
<style name="AppTheme" parent="android:Theme.Black">
<!-- Customize your theme here. -->
</style>
I am happy with that theme, except I want to change the background color of a button. Here is how it looks by default:
Here's what happens when I add a background color to this button (android:background="#color/play_bg"):
Hey!? It basically changed all the button's size, padding and margins!
So I managed to get the expected result using the backgroundTint property (android:backgroundTint="#color/play_bg"):
Unfortunately, this is only supported since version 21 of the API, which is not acceptable for me.
So two questions:
Why does changing the background messes with the rest of the button's properties?
How do I get the expected result without backgroundTint?
And a bonus question: How can I get the expected result programmatically (I have dynamic buttons in my app, so this would be very useful)?
You can change this color in your Java File. When your main class loads you can take an object of this button and then change color.
Here is how you define this button in Manifest file :
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PLAY"
android:id="#+id/btn1"
... />
Now in your Java file when you are adding this XML layout you need to
Button b = (Button)findViewByID(R.id.btn1);
b.getBackground().setColorFilter(0xFFFF0000,PorterDuff.Mode.MULTIPLY);
You may also use COLOR:
COLOR.RED
The code below sometimes does not work for me :-
b.setBackgroundColor(int color)
In my case I will be doing in this process
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp"
android:background="#color/play_as"
android:padding="8dp"
android:text="Button" />
Or you can use this link which is more easy way of creating the buttons
First-time Android dev, though have used C# and Java in the past.
Trying to make a simple, Windows 8-like GUI. At the moment I have one tile (ImageButton) with a background color set in activity_main.xml.
<ImageButton
android:id="#+id/btn1"
android:layout_width="120dp"
android:layout_height="120dp"
android:background="#FF0000"
android:onClick="changeColor"/>
And I have a function to change the color in MainActivity.java.
public void changeColor(){
ImageButton btn1 = (ImageButton) findViewById(R.id.btn1);
btn1.setBackgroundColor(Color.GREEN);
}
Compiles fine, but every time I click the red square, the app crashes.
I'm assuming there's something fundemental about how Android is developed that I'm missing which is leading to a very obvious mistake. Is there a better way to be doing this rather than ImageButtons?
Thanks!
Compiles fine, but every time I click the red square, the app crashes.
Because when adding android:onClick in xml then method must be public and accept a View as its only parameter which we want to call on View click:
public void changeColor(View view){
ImageButton btn1 = (ImageButton) findViewById(R.id.btn1);
btn1.setBackgroundColor(Color.GREEN);
}
It's better to create a selector and set it as backgraund to the button.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/button_pressed" />
<item android:color="#color/button_normal" />
</selector>
Hope it'll help you.
P.S. useful link
Is there a better way to be doing this rather than ImageButtons?
Yes, ImageButtons are mainly for creating a 'clickable' image. If you simply want a colored button, a regular Button will do fine.
You can do this by setting your Buttons background right from XML using a selector with a Drawable state list.
A good example can be found here: https://stackoverflow.com/a/3882151/1683141 (a color will also qualify as a Drawable)
Why isn't my current code working?
You should add the view as parameter to your method like this:
public void changeColor(View view){
view.setBackgroundColor(Color.GREEN);
}
I have an app that for some reason, on the latest Android SDK (4.4) launches to a black screen.
I can still hear the activity behind it (for example if I click on somewhere in the black, a button sound is clicked, so Its almost like the screen is loaded behind the black screen).
It works fine on my device which is a Nexus 4 running 4.4, it appears to be an issue on the later version (Nexus 5) devices.
It also shows the banner ad (admob) that I have, so it literally is a case that it seems to be an issue with the background image file.
//#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
mGLSurfaceView = new CCGLSurfaceView(this);
CCDirector.sharedDirector().setScreenSize(CCDirector.sharedDirector().winSize().width,
CCDirector.sharedDirector().winSize().height);
CCDirector.sharedDirector().setDeviceOrientation(CCDirector.kCCDeviceOrientationPortrait);
CCDirector.sharedDirector().getActivity().setContentView(mGLSurfaceView, createLayoutParams());
InitParam();
getAdmob();
}
Activity game xml is;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".GameActivity" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY" />
</RelativeLayout>
width & height of the imageview is "wrap content" however the scaletype is "fitXY".
thats kind of saying 2 different things to the device.
if that image should be full screen change it's width & height to match/fill parent.
Check onCreate(), onStart() and onResume() methods in your code, you might be doing some time consuming, blocking tasks. If so, load heavy background tasks on a separate thread.
Profile your code with Traceview and dmtracedump to check what is taking more time.