In iOS, if I set a button's background to an image, when I press the button, the whole content of the button (including the text) will be shadowed. Can I achieve the same effect in Android, or do I have to use different images for different states? Also, even if I use different images for different states, how do I make the text also shadowed? A dirty way is to set a OnClickListener to the button and programatically shadow the text when pressed, but are there any other ways?
I´ve been trying to find a solution for this for a while now but couldn´t find anything so I came up with a pretty neat solution which works on all image buttons. Just like iOS.
Create a Black, 10% transparent image and save it as PNG. I call it button_pressed.png. You can use this image, http://img84.imageshack.us/img84/7924/buttonpressed.png
Create a drawable called something relevant, I call it "button_pressed_layout.xml"
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android=" http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/button_pressed" />
</selector>
Now put your button image in the LinearLayout and then the Button inside the LinearLayout. In the Button use button_pressed_layout.xml as background.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/button_image">
<Button
android:id="#+id/myButtonId"
android:text="#string/Continue"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/button_pressed_layout"
android:textColor="#FFF"
android:textSize="16dp" >
</Button>
</LinearLayout>
That´s it!
To get a pressed-state without creating a 2nd button image, I created an OnTouchListener to change the button's alpha. This is not the most beautiful pressed state, but gives an effective automatic behavior.
public class PressedStateOnTouchListener implements OnTouchListener
{
PressedStateOnTouchListener( float alphaNormal )
{
mAlphaNormal = alphaNormal;
}
public boolean onTouch( View theView, MotionEvent motionEvent )
{
switch( motionEvent.getAction() ) {
case MotionEvent.ACTION_DOWN:
theView.setAlpha( mAlphaNormal / 2.0f );
break;
case MotionEvent.ACTION_UP:
theView.setAlpha( mAlphaNormal );
break;
}
// return false because I still want this to bubble off into an onClick
return false;
}
private float mAlphaNormal;
}
In your Activity, apply this listener to each button:
Button theButton = (Button)findViewById( R.id.my_button_id );
theButton.setOnTouchListener( new PressedStateOnTouchListener( theButton.getAlpha() ));
In order to give the button itself different effects, I believe you need to use custom images, as seen here and, in less detail here As for the text, this post looks like it would do the trick for the shadow
Related
Actually, I use a ListView and when I use setClickable(false) I have the animation as if I clicked on a button you see? The animation that shows you click. Which is not normal, I think, basic.
And when I use setClickable(true) I no longer have the animation, as well as if I use
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
And i would like to use the OnClickListener but I think it would be better for the user to see that he can click, so to have the animation when you click.
So, I'd like to see when the user clicks on an item in the list, it does the action I want (I'll add that later) but let's imagine a Toast but it displays the effect as if you click on a button. The effect i got if i use setClickable(false) (the default setting).
That's the ripple effect !
In the row's layout of the ListView just add:
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
This will add the Ripple effect. If you want to show it on top of the other views, use the forground attribute:
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
add this foreground:?attr/selectableItemBackground to your view attribute, it should work
I'm trying to do a simple imageview with a colored background that when pressed change the color and at the end of the touch if it is outside the image area then it would return to the original color or else start another activity (like a button); so i decided to implement an onTouchListener in my activity using a kotlin lambda.
This is the code:
imageview.setOnTouchListener{ view: View, event: MotionEvent ->
val rect = Rect(view.left, view.top, view.right, view.bottom)
when(event.action){
MotionEvent.ACTION_DOWN->{
view.setBackgroundColor(dark_color)
}
MotionEvent.ACTION_UP-> {
if (rect.contains(event.x.toInt(), event.y.toInt()))
startActivity(Intent(this, NewActivity::class.java)
else{
view.setBackgroundColor(normal_color)
}
}
}
true
}
And it works fine but while i was testing it i saw that the new activity was starting else if the touch is out of the image area, so i used the Log function to report the cordinates of the touch and i noticed that the cordinates (when MotionEvent.ACTION_UP was triggered) where different from the point that i was touching on the screen.
Is it possible that the system is bugged ?
(p.s. i tried also on the emulator and i had the same result and I can't use xml selectors)
Thanks for help!
The only thing you need to do is to create a selector. You set the selector as a background to your ImageView. So the selector manage the colour automatically (when the image is pressed or not). Then you set a listener on your ImageView to manage the click event. If the user moves his finger out of the ImageView area, the listener will NOT be triggered (it's automatically managed).
In your Java code
imageView.setOnClickListener(new View.OnClickListener {
public void onClick(...){
// Start the Activity
}
});
in your XML
<ImageView
android:background="#drawable/my_selector"
//...
my_selector.xml (must be in the drawable folder)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/default_pressed" android:state_pressed="true" />
<item android:color="#color/default_not_pressed" />
</selector>
I have a number of ImageButtons in a layout. The image resources are 32x32 px. They all have the same attributes:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/ibButton1"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:layout_weight="0"
android:src="#drawable/not_selected"
android:layout_gravity="center_vertical"
android:background="#null"/>
In my fragment, I'm doing:
final ImageButton button1 = (ImageButton)view.findViewById(R.id.ibButton1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
isSelected = !isSelected;
if (isSelected ) {
button1.setImageResource(R.drawable.selected);
}
else {
button1.setImageResource(R.drawable.not_selected);
}
}
});
However, most times I need to click over 5 times on the button for it to register the click.
Should I need to increase the image size or is there a better way to listen to clicks? Should I use onClick attribute instead?
Provide some padding to increase the Tap area.
android:padding="10dp"
Perhaps, the size of the image is too small(as #Shoeb Siddique said) to get touch event on the image. You can increase the padding or size of image to improve the probability to touch the image.
It seems to me , you don`t need an ImageButton, but a ToggleButton with to states.
http://developer.android.com/guide/topics/ui/controls/togglebutton.html
and please remove android:clickable="true" , it is not needed, because it is a button, which mean, it is true by default. If it would be an TextView, it would needed.
Extract Image With Touch zone I Mean Transparent Background
for Eg : the Give Image is 86 * 70 px So When Ever User touches round that Transparent background 86* 70px you can fire event
I have a tablelayout with two rows each consisting of two imageview. I want to achieve result as below. I have tried few solutions mentioned in stackoverflow but somehow I have not found a way to achieve this. Each imageview is looks as below
<ImageView
android:id="#+id/imageViewY"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#drawable/cell_border"
android:clickable="true"
android:padding="2dp"
android:src="#drawable/letter_y" />
If you have any idea or solution to achieve this , i would like to request for your help. Thanks in advance.
use transparent color #11000000 as background of imageview
Here 11 is a Transparency Value of color 000000(means Black color)
and you can set alpha programatically or through xml for setting transparency
now If Set Alpha You said deprecated and don't want to take risk by using this then just set color of image view
i just explain how to handle 1st imageview's click
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v==imageview1){
//set lighter dark layer on click of image 1 and reset fully transparent layer on other image
imageview1.setBackgroundColor(Color.parseColor("#11000000"));
imageview2.setBackgroundColor(Color.parseColor("#00000000"));
imageview3.setBackgroundColor(Color.parseColor("#00000000"));
imageview4.setBackgroundColor(Color.parseColor("#00000000"));
}
}
I have a gallery. Each slide has a button inside.
I have a custom layout which with I'm inflating the slides.
Attached a click listener to the button and it works well, gallery also scrolls normally.
But when I press on the gallery outside of the button, the button is also pressed and turns blue. This doesn't trigger the onClickListener of the button. But it makes the button look like it was pressed and I don't want that.
Tried setting all listeners of the gallery to empty implementations but no effect...
Thanks in advance.
Edit: Attached an empty click listener to the custom layout and now the button doesn't become blue anymore but the gallery doesn't scroll because the event is consumed. Will see what can be done...
Found a workaround for this. It's horrible, but it works.
First of all, the part of Gallery's code responsible for my problem is this:
public boolean onDown(MotionEvent e) {
// Kill any existing fling/scroll
mFlingRunnable.stop(false);
// Get the item's view that was touched
mDownTouchPosition = pointToPosition((int) e.getX(), (int) e.getY());
if (mDownTouchPosition >= 0) {
mDownTouchView = getChildAt(mDownTouchPosition - mFirstPosition);
mDownTouchView.setPressed(true);
}
// Reset the multiple-scroll tracking state
mIsFirstScroll = true;
// Must return true to get matching events for this down event.
return true;
}
More exactly this line:
mDownTouchView.setPressed(true);
Here the layout of my slide is pressed and the default behaviour of setPressed of LinearLayout is dispatching it to all childrens so all children are pressed.
First I tried making a subclass of Gallery and override onDown. If I just returned false and nothing else, it worked but the slides got strange behaviour of jumping to the next slide when touched. That was because of this line:
mFlingRunnable.stop(false);
Which was not executed. Since this variable is private and related to everything else in Gallery class I didn't find a way to use it from the subclass. I tried also copying all the Gallery code, but it also didn't work, because it uses lot of things which only have package access... etc.
So I created a subclass of LinearLayout, which overrides onSetPressed:
public class LinearLayoutOnSetPressedDoNothing extends LinearLayout {
public LinearLayoutOnSetPressedDoNothing(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void setPressed(boolean pressed) {
}
}
And use that in my layout instead of the LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<com.test.LinearLayoutOnPressDoNothing
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- content -->
</com.test.LinearLayoutOnPressDoNothing>
And well, this works.