ImageButton background color change onClick - java

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);
}

Related

Correctly animate buttons which have elevation/drop shadow set

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();
}

DrawerLayout on top of Actionbar

When using the drawer layout is there a way to overlay the drawer view over the action bar? I do not want to hide the action bar when the drawer is shown. I want the action bar to simply stay put, but be sent to the background. An example of this is the iOS Play Music app...
My current implementation hides and shows the action bar when the drawer state changes, but I do not like this user experience.
public void onDrawerClosed(View view) {
getActionBar().show();
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().hide();
invalidateOptionsMenu();
}
I searched the web in order to find any good solution for this problem and haven't found. So I did a trick that did this.
First of all we need to request action bar overlay feature. So in onCreate() of your activity, before setContntView() call: requestWindowFeature(com.actionbarsherlock.view.Window.FEATURE_ACTION_BAR_OVERLAY);
It will make everything including navigation drawer draw behind action bar. We don't need this, so we need to set the top margin of our FrameLayout which hosts our fragments in the activity with the exact height of the action bar. In the layout file of the activity we need to do the following:
<!-- Framelayout to display Fragments -->
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize" />
It will make only navigation drawer appear behind the action bar.
Now we will hide the action bar when the navigation drawer is opened on half, and will show it when the drawer is nearly closed. To do this we need to make the following in the activity:
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
if(slideOffset > 0.5){
actionBar.setBackgroundDrawable(null);
actionBar.hide();
} else {
actionBar.show();
if(slideOffset < 0.1){
actionBar.setBackgroundDrawable(layerDrawable);
}
}
}
As you can see I also change the background drawable of the action bar to make it transparent when before I begin to hide it, and change it back with my custom background when I show it back.
My custom background is a layerListDrawable which is all transparent but have a divider in bottom with some shadow.
And to achieve this I have defined the following layer-list in XML:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
<shape android:shape="rectangle">
<solid android:color="#android:color/transparent"/>
</shape>
</item>
<item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
<shape android:shape="rectangle">
<solid android:color="#afafaf"/>
</shape>
</item>
<item android:top="0dp" android:left="0dp" android:bottom="0dp" android:right="0dp">
<shape android:shape="rectangle">
<gradient
android:angle="270"
android:startColor="#88afafaf"
android:endColor="#33afafaf"
/>
</shape>
</item>
</layer-list>
And to get the background I need from this XML I do the following in the activity:
final ActionBar actionBar = getSupportActionBar();
final LayerDrawable layerDrawable = (LayerDrawable) getResources()
.getDrawable(R.drawable.shadow_divider);
final TypedArray styledAttributes = getTheme().obtainStyledAttributes(
new int[] { R.attr.actionBarSize });
int topOffset = (int) (styledAttributes.getDimension(0, 0));
styledAttributes.recycle();
layerDrawable.setLayerInset(1, 0, topOffset - 3, 0, 2);
layerDrawable.setLayerInset(2, 0, topOffset - 2, 0, 0);
actionBar.setBackgroundDrawable(layerDrawable);
where R.drawable.shadow_divider is the XML layer-list I have defined earlier.
It looks really great! Hope it can help someone.
EDIT
I had a small bug here which can be a reason of a crush sometimes. Here is the fixed code:
`
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
**android:paddingTop="?attr/actionBarSize"** />`
It should be paddingTop not layout_marginTop!
That's the proper effect in Android defaults. If you want to emulate the iOS effect, you'll probably have to do it yourself, because AFAIK the drawer component of the support library doesn't allow such type of configurations.
Anyway, every time a programmer codes a lot just to emulate some fancy (and much probably not worthy) iOS effect in Android, a little cat dies...
I don't think you'll be able to do this with Android's provided Navigation Drawer (without doing something really hacky), since doing this really goes against Android design patterns. If you want a library that does what you're looking for, I've used this library before Android came out with it's own widget, and it does what you're looking for.
I found the answer in my question, also added an example project for reference. You can take a look to see if it works for you.
Android Navigation Drawer on top ActionBar
You can achieve this with ActionBarSherlock.
http://actionbarsherlock.com/
You will be able to do it but the drawer will look so awkward that you will not like it. I had the same requirement and I ended up using Radio Buttons customized to appear as tabs. You can also try hiding the tabs when the drawer opens and vice versa, but that certainly is not what you want here.
You can try to use ViewPager, tabbed indicator such PagerTabStrip and/or TabPageIndicator.
Source.

android generate resource on the fly

I would like to generate a pressend button design and load it on the fly.
The static version it is an xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- selected state -->
<item android:drawable="#drawable/bt_back_pressed" android:state_pressed="true" android:state_selected="false"/>
<item android:drawable="#drawable/bt_back_pressed" android:state_pressed="false" android:state_selected="true"/>
<item android:drawable="#drawable/bt_back_pressed" android:state_pressed="true" android:state_selected="true"/>
<!-- unselected state (default) -->
<item android:drawable="#drawable/bt_back_normal"/>
</selector>
which is located in the /res/drawable folder. When I want to use it just a line of the code:
android:background="#drawable/bt_back"
Now, the current project loads the design for the button from the server side, let it be the bt_back_normal.png loaded from www.somehost.com/some/resource/bt_back_normal.png.
It would be nice if I could get an API to generate the "pressed" version ( some darker) and link it at events chain to show, when needed.
Right now there is no visual effect, when the user press the button.
How can I generate that xml equivalent on the fly? -generate a pressed version and set to show when needed.
Thanks.
I think you're looking for the StateListDrawable class. You can create these in code, add states to it (e.g. your downloaded pressed png file) and then set it to your button with button.setBackgroundDrawable(stateList).
No, you can't do this on the fly. If you wanna use dynamically generated pressed drawables you should implement OnTouchListener and set needed background inside of it.
This is kind of a workaround for that, but you could just override the OnClickListener for the button, and change the background of the button inside there. ie.
final Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
button.setBackgroundDrawable(R.drawable.button_pressed);
}
});
EDIT:
I didn't realize you wanted to change the states; thought you just wanted to show it was pressed. In that case, use StateListDrawable: http://developer.android.com/reference/android/graphics/drawable/StateListDrawable.html

How can i draw a circle that compatible with all android device with fixed radius?

I need to create a program, that have 5 radius buttons. When i'm click on these each button i want to adjust my circle radius.(Circle should have same size in all android phones).
pls help me to find this...
Deducting the screen size before you create a circle and act based on that is a elegant way ,
There are difference sizes of screens in android devices,
so find out the screen size place your co-ordinate values according to the found screen size,
If drawing is only one option for you then the following
thread will be helpful for you to achieve this,
Compatible Canvas draw tip
If not, then button backgounds should be 9 patch image is always better.
Hope , you will find it useful.
You could create a circle-shape in xml and set this as background resource to a button or an imageButton, or you could do your own button-class and override onDraw method. A tutorial with shape is here:
http://dandar3.blogspot.de/2012/10/android-custom-round-buttons.html
or here:
http://yekmer.posterous.com/how-to-make-rounded-buttons-on-android
Instead of using "rectangle" at the shape, You could use "oval".
I donĀ“t know if I understand You right, but making a button that had the same size on every phone is not a good way. Views had to be independent, a view should be created in a way, that it is adjusted to the individual screen size. To do so, use "dp" units in your xml layouts.
Now here is my example:
1.) first create a shape-drawable in the drawable folder:
round_button_oval_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#00ced1" />
</shape>
2.) create a second shape in drawable folder:
rounded_button_oval_shape_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#008b8b" />
</shape>
3.) create a selector in the drawable folder:
rounded_button_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/rounded_button_oval_shape_pressed"
android:state_pressed="true"></item>
<item android:drawable="#drawable/round_button_oval_shape"
android:state_pressed="false"></item>
<item android:drawable="#drawable/round_button_oval_shape"></item>
</selector>
4.)create your main-layout
main.xml
<LinearLayout 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"
android:background="#000000"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
android:textColor="#ff0000" />
<Button
android:id="#+id/rounded_button"
android:layout_width="250dp"
android:layout_height="250dp"
android:background="#drawable/rounded_button_selector" />
</LinearLayout>
If you have done this parts, you could anything do with that button in your activity.
RoundedButtonDemo.java
public class RoundedButtonDemo extends Activity {
private Button mRoundedButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mRoundedButton = (Button) findViewById(R.id.rounded_button); //initialize your button
mRoundedButton.setOnClickListener(new OnClickListener() { // set Button on click listener
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(RoundedButtonDemo.this, //show a toast when pressing button
R.string.rounded_button_message, Toast.LENGTH_LONG)
.show();
}
});
}
}
The shapes and the selector are needed for showing a pressed behavior of the button. The first shape is a normal button, which is not pressed. the second one is a shape that is pressed. The selector is using the two shapes for showing the pressed state to the user. To get this, set the selector as background to your button in your main.xml .

android oval shape dialog

i have an application , it has a button , when pressed it will fire a dialog with the default dialog shape , i wonder if i can change the default shape of dialog to an oval shape and also to apply special style to it ,
as explained in the images attached below :
1- the Default Dialog Shape:
2-The Oval Dialog Shape (which i try to achieve):
my dialoge code :
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.custom_dialog);
TextView text = (TextView) dialog.findViewById(R.id.dialog_text);
text.setText(Html.fromHtml(getString(R.string.text_4)));
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.pic);
Button dialogButton = (Button) dialog.findViewById(R.id.dialog_Button);
dialogButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
});
}
style code of default dialog:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="2dp" android:height="2dp" android:color="#B22222" />
<solid android:color="#FCE6C9" />
<padding android:left="2dp" android:top="2dp" android:right="2dp"
android:bottom="2dp" />
<corners android:radius="5dp" />
</shape>
i hope to have this done by code rather than using 9-patch image so it will be easy to control the dilaoge dimensions and adjust the text inside it as i neeed ,
Any advice will be appreciated , thanks .
Not exactly sure how to do this on android, but the approach I use in java is make the JFrame or JDialog rendered surface transparent and then draw my own custom shape inside. To make them transparent I use AWTUtilities.setWindowOpacity
On this article you will find another ideas, like capturing the desktop before the frame or dialog is rendered and using it to patch your frame:
http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html
More information:
http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/
Here you have an implementation, not for android but it may help:
http://www.codeproject.com/KB/java/shaped-transparent-jframe.aspx
Neat idea. On Android, to give an activity a transparent background, put this in your manifest file:
<activity android:name=".MyActivity" android:theme="#android:style/Theme.Translucent.NoTitleBar" />
Then, in your layout file for that activity, add this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/myRoundBackground" />
<TextView
android:id="#+id/myImageViewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/myImageView"
android:layout_alignTop="#+id/myImageView"
android:layout_alignRight="#+id/myImageView"
android:layout_alignBottom="#+id/myImageView"
android:layout_margin="1dp"
android:gravity="center"
android:text="Hello"
android:textColor="#000000" />
</RelativeLayout>
Then you can programmatically set the text on the TextView with the id myImageViewText .
Have a look at this quick action menu totorial. Try applying this tutorial with shape = oval background. I think you will get what you are trying to achieve.
I think a transparent background with image sliced in oval for will work for you. and place the button to left of the oval image.
THis method is similar to the one you are currently trying :
In your custom_dialog.xml give the relative layout an android:background="#drawable/ovaldialog" .
And in the ovaldialog.xml try giving the same parameters you are giving to edit the style by giving android:shape="oval" and also give the parameters to corners such as android:topLeftRadius="8dp" and android:bottomRightRadius="10dp" and play with those values until you get a desired kind of shape. To give the red color to the dialog give it a stroke of width 2/3dp and an android:color value.
Hope this helps

Categories