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>
Related
Currently I have a GridView that holds some ImageViews. The GridView implements setOnItemClickListener. When the onItemClick occurs, the user gets a dialog and on back pressed or on dismiss, he returns to the current GridView.
Till now everything works fine.
I would like to know if there is a way to change the selected imageView (with another image, or even just the alpha).
I have tried inside the setOnItemClickListener to change the image, but when I try to change it back to it's normal image after the dialog.dismiss() call, a white screen pops up for some milliseconds. Although, the image is set correctly, I would like to avoid this white image.
I have tried to implement the GridView.setOnTouchListener, but I would get only a white screen (for some milliseconds) and no other operation would be executed (no pop up dialog).
I even tried to implement OnTouchListener inside the ViewHolder class and although it seemed to work with some problems (changing the alpha on ACTION_DOWN was permanent, so I had to reselect the same item to change the alpha back to normal), the setOnItemClickListener wouldn't work at all.
Can someone help me with this?
Thanks in advance!
Just for anyone having the same problem, I used TransitionDrawable. Inside my imageAdapter, I loaded the transition xml files:
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/soft"/>
<item android:drawable="#drawable/soft_pressed"/>
</transition>
and on gridview.setOnItemClickListener, I used this sample of code:
ViewHolder holder = (ViewHolder) v.getTag();
final ImageView imageview = holder.image;
((TransitionDrawable)imageview.getDrawable()).startTransition(2000);
And to execute the next command (some delay is needed):
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
YourMethod(...);
//reverse the transition
((TransitionDrawable)imageview.getDrawable()).reverseTransition(2000);
}
}, 2000);
As I am working on keyboard, we know on default keyboard on any android device when we click any button larger image is flashed above button, I don't know exactly this effect, ut I have tried using below code.
Button which is clicked in my Keyboard.xml:
<Button android:id="#+id/xBack"
android:background="#drawable/back_high"/>
Above back_high is my xml file.
back_high.xml file is,
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/back_click"
android:state_pressed="true" />
<item android:drawable="#drawable/back"
android:state_focused="true" />
<item android:drawable="#drawable/back" />
</selector>
Its working successfully, but image is flashed at same place where I clicked, but I need this image is displayed on above button, as happening on android default keyboard.
your setting the background of that specific button, so if you want it to appear above the button make sure you use a frame layout as the overall layout of the keyboard and then have a single extra imageview that you switch location and resource when you click on a button. you won't need the selector anymore.
Frame layout's will let you put multiple views on top of each other.
This Link :
Why not make this programmatically and not in UI mode?
There are several, depending on what kind of flashing you mean.
You can, for example, use alpha animation and start it as your button first appears. And when the user clicks button, in your OnClickListener just do clearAnimation().
Example:
public void onCreate(Bundle savedInstanceState) {
final Animation animation = new AlphaAnimation(1, 0); // Change alpha from fully visible to invisible
animation.setDuration(500); // duration - half a second
animation.setInterpolator(new LinearInterpolator()); // do not alter animation rate
animation.setRepeatCount(Animation.INFINITE); // Repeat animation infinitely
animation.setRepeatMode(Animation.REVERSE); // Reverse animation at the end so the button will fade back in
final Button btn = (Button) findViewById(R.id.your_btn);
btn.startAnimation(animation);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(final View view) {
view.clearAnimation();
}
});
}
Also This Answer.
I want to change the background color of a customView when it's pressed and slightly "remove" this background color when the view losses the "pressed-state". However, I googled this question and found a solution using a StateListDrawable. I've tried this within my customView (which is added to a ListView programmatically), but just the "normal color" was set to my view. When I touched the view nothing happens. What's going wrong?
the selector xml-file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#color/bckgr" />
<item
android:drawable="#color/transparent" />
</selector>
within the constructor of my custom view:
this.setBackgroundResource(R.drawable.list_item_bckgr);
you have to apply your background to the View the Adapter fills up (the view your getView implementation is returning) not to the ListView self
Try setting android:descendantFocusability to true on the ListView.
Hey Are you making the view focussable and clickable, use in the constructor:
setClickable(true);
setFocusable(true);
May be your view isn't getting focus.
You need to set the OnTouchListener to handle touch events. When the view is touched, change the background, and when the view is 'untouched', change the background back to the original.
To set the listener, call the View.setOnTouchListener() function of your custom view with the OnTouchListener you create to handle these events.
Here is the reference to OnTouchListener:
http://developer.android.com/reference/android/view/View.OnTouchListener.html
I imagine that you have an override method to the OnTouch() method, what I would do is create an instance variable (class var) that would hold the image that you want to have as a background, and set it in your OnTouch() method. Then, Override your OnDraw() method which would give you a reference to the canvas, and use the canvas.DrawBitmap() to draw your background.
This answer shows you more details on how to draw the bitmap
Setting background image in a custom view
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.
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