How to fade ImageView after drag/drop is done? - java

I have one ImageView (drag and drop) and one button that fades the Image. drag and drop works fine and fade button initially works fine to. The issue arises when the image is dragged and THEN fade button is pressed.
it seems that it only fades the original place the image was(before drag and drop). I would like to fade the actual image after its been dragged. Here is a picture explaining :enter image description here
my main_activity.xml:
<?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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="app.com.example.muhammad.downloadmanagerexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="#+id/Hello"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView"
android:src="#drawable/images"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fade"
android:id="#+id/buttonFade"
android:layout_below="#+id/imageView"
android:layout_centerHorizontal="true"
android:layout_marginTop="77dp" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
ImageView image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.imageView);
//downloadFile(path);
image.setOnTouchListener(this);
Button fadeButton = (Button) findViewById(R.id.buttonFade);
fadeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(1000);
animation.setRepeatCount(1);
animation.setRepeatMode(Animation.REVERSE);
image.startAnimation(animation);
//appIcon.animate().alpha(0.0f).setDuration(1000);
//appIcon.animate().alpha(1.0f).setDuration(1000);
}
});
}
PointF DownPT = new PointF(); // Record Mouse Position When Pressed Down
PointF StartPT = new PointF(); // Record Start Position of 'img'
#Override
public boolean onTouch(View v, MotionEvent event) {
int eid = event.getAction();
switch (eid)
{
case MotionEvent.ACTION_MOVE :
PointF mv = new PointF( event.getX() - DownPT.x, event.getY() - DownPT.y);
image.setX((int)(StartPT.x+mv.x));
image.setY((int)(StartPT.y+mv.y));
StartPT = new PointF( image.getX(), image.getY() );
break;
case MotionEvent.ACTION_DOWN :
DownPT.x = event.getX();
DownPT.y = event.getY();
StartPT = new PointF( image.getX(), image.getY() );
break;
case MotionEvent.ACTION_UP :
// Nothing have to do
break;
default :
break;
}
return true;
}
}
I have been searching about this topic and couldn't find an excat solution so thought about asking it. Thank you in advance. really appreciate this site and all of the people who contribute to it :)

you actually create new image every time.You are not dealing with one image only.You do not have same instance of image.when you fade you are deleting image.And when you drop image after dragging then you recreate image.If you find my answer appropriate then upvote me.Thanks

Related

Spin ImageView without losing height and width in android studio

i am developing a roulette game for learning while my friend ask me to make spinning wheel shape from circle to oval. after changing shape of ImageView to an oval and trying to rotate ,it's height and width are swapping according to each 90-degree rotation. while height and width should not change as i need, following are codes i am using and screenshot attached
thanks for your time .
layout_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/iframe"
android:layout_centerInParent="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="150dp"
android:src="#drawable/wheel2min_300x300"
android:scaleType="fitXY"
android:id="#+id/wheel_image"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal"
android:layout_marginTop="25dp"/>
<ImageView
android:layout_width="50dp"
android:layout_height="40dp"
android:src="#drawable/target_147x300"
android:scaleType="fitXY"
android:id="#+id/wheel_pointer"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal"/>
</FrameLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="press to spin"
android:id="#+id/spin_button"
android:layout_below="#id/iframe"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
private Button button;
int h,w;
CountDownTimer countDownTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.wheel_image);
button = findViewById(R.id.spin_button);
h=imageView.getHeight();
w = imageView.getWidth();
Random random = new Random();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
button.setEnabled(false);
// reading random value between 10 to 30
int spin = random.nextInt(20)+10;
// since the wheel has 10 divisions, the
// rotation should be a multiple of
// 360/10 = 36 degrees
spin = spin * 36;
// timer for each degree movement
countDownTimer = new CountDownTimer(spin*20,1) {
#Override
public void onTick(long l) {
// rotate the wheel
float rotation = imageView.getRotation() + 2;
imageView.setRotation(rotation);
}
#Override
public void onFinish() {
// enabling the button again
button.setEnabled(true);
}
}.start();
}
});
}
UI i want even when rotation

Writing function for onTouchListner, when Imageview held for more than 2 seconds?

I am working on a app to unlock a door by sliding an Imageview upwards and holding it for a a few seconds. I have designed a layout in a ConstraintLayout Layout.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_color"
android:padding="50dp">
<ImageView
android:id="#+id/background_image"
android:layout_width="match_parent"
android:layout_height="400dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/switch_button_background" />
<ImageView
android:id="#+id/fill_image"
android:layout_width="match_parent"
android:layout_height="390dp"
app:layout_constraintBottom_toBottomOf="#+id/background_image"
app:layout_constraintEnd_toEndOf="#+id/background_image"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/background_image"
app:layout_constraintTop_toTopOf="#+id/background_image"
app:layout_constraintVertical_bias="0.4"
app:srcCompat="#drawable/switch_button_fill_color">
</ImageView>
<LinearLayout
android:id="#+id/linear_view"
android:layout_width="200dp"
android:layout_height="400dp"
android:clipChildren="true"
android:gravity="center|bottom"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="#id/fill_image"
app:layout_constraintEnd_toEndOf="#+id/fill_image"
app:layout_constraintStart_toStartOf="#+id/fill_image"
app:layout_constraintTop_toTopOf="#+id/fill_image"
app:layout_constraintVertical_bias="0.498">
<ImageView
android:id="#+id/thumb_icon"
android:layout_width="230dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:adjustViewBounds="true"
android:src="#drawable/trimmy"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.48"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.72" />
</LinearLayout>
<ImageView
android:id="#+id/img_unlock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="#id/fill_image"
app:layout_constraintEnd_toEndOf="#id/fill_image"
app:layout_constraintStart_toStartOf="#id/fill_image"
app:layout_constraintTop_toTopOf="#id/fill_image"
app:layout_constraintVertical_bias="0.23000002"
app:srcCompat="#drawable/ic_unlock" />
<ImageView
android:id="#+id/main_login"
android:layout_width="91dp"
android:layout_height="60dp"
app:layout_constraintBottom_toTopOf="#+id/background_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7"
app:srcCompat="#drawable/team_xx" />
I have tried to handle dragging event by OnThouchListner:
thumbIcon.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
yDown = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float movedY;
movedY = event.getY();
float distance = movedY - yDown;
float currentDistance = thumbIcon.getY() + distance;
if (currentDistance > 450) {
return false;
} else if (currentDistance < 50) {
return false;
} else {
thumbIcon.setY(thumbIcon.getY() + distance);
}
break;
case MotionEvent.ACTION_UP:
undoAnimation();
break;
}
return true;
}
});
I added if statements to limit Imageview moving bounds. However since I want to hold the thumb image upwards for a few seconds. I have no idea how to code this task? It would be great if anyone could help me.
EDIT:
I have came up with sort of workaround to tackle this issue. Although it's not perfect but it is the only possible solution I could come up with.
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// ...
countDownTimer.start();
break;
I have added a countDownTimer to my code. for going off in two seconds. Then I check if the thumb icon or my moveable view is at the right position. then I execute whatever method I want in onFinish() block of my code:
countDownTimer = new CountDownTimer(2000, 250) {
#Override
public void onFinish() {
if (linearLayout.getY() >= thumbIcon.getY()) {
//Execute my code here...
}
I leave this question unanswered since this approach is not ideal. And this solution was inspired by Henry Twist comment.
You can set long click listener to your Linear Layout of your Image View it-self.
thumbIcon.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
...
}
});
Just noticed that your linear layout around your image view is smaller than image view.
To hold the thumb image upwards for a few seconds you can start a Long Click Handler with a delay in milliseconds in your MotionEvent.ACTION_DOWN and you can remove this handler in on MotionEvent.ACTION_UP. When the Long Click handler triggered you can set a boolean value eg: enabledDragging = true where then in your MotionEvent.ACTION_MOVE you can use this flag to activate your move logic.
Example of this will be like below:
thumbIcon.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
startLongClickHandler();
break;
case MotionEvent.ACTION_MOVE:
if(!enabledDragging)
return true;
//your move logic .....
break;
case MotionEvent.ACTION_UP:
removeLongClickHandler();
break;
}
return true;
}
});
And the Long Click Handler methods will be like:
private boolean enabledDragging = false;
private void startLongClickHandler(){
longClickHandler.postDelayed(mLongPressed, 2000);//2sec
}
private void removeLongClickHandler(){
longClickHandler.removeCallbacks(mLongPressed);
enabledDragging = false;
}
private final Handler longClickHandler = new Handler();
private Runnable mLongPressed = new Runnable() {
public void run() {
enabledDragging = true;
}
};

Android on DragEvent fires when dragging anywhere in the screen

I have a simple layout that becomes visible once a drag event starts:
<RelativeLayout
android:id="#+id/onDragMenu"
android:visibility="gone"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="blablabla"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_marginTop="75dp"
android:textAlignment="center"
/>
<ImageView
android:id="#+id/smsDragButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="25dp"
android:layout_marginBottom="25dp"
android:src="#mipmap/sms_icon"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:background="#drawable/rounded_button"
android:padding="5dp"
/>
<ImageView
android:id="#+id/callDragButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="25dp"
android:layout_marginBottom="25dp"
android:src="#mipmap/phone_icon"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:background="#drawable/rounded_button"
android:padding="5dp"
/>
</RelativeLayout>
And some code to handle what happens when something is dragged onto one of the image views:
View callButton = onDragMenu.findViewById(R.id.callDragButton);
callButton.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()){
case DragEvent.ACTION_DRAG_ENTERED:
// blablabla
break;
case DragEvent.ACTION_DRAG_ENDED:
// blablabla
break;
}
return true;
}
});
However, onDrag is triggered the second I start the drag(outside the buttons), with ACTION_DRAG_STARTED, and ACTION_DRAG_ENTERED is never hit.
Finally, when I let go, ACTION_DRAG_ENDED is hit, with coordinates (0,0).
I'm quite new to Android, and probably missing something basic.
Please help.
Thanks
Set the visibility of Relative layout to INVISIBLE instead of gone.
Instead of Using Drag event,Use onTouch drag event.
MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class MainActivity extends Activity implements View.OnTouchListener {
private ImageView mImageView;
private ViewGroup mRrootLayout;
private int _xDelta;
private int _yDelta;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRrootLayout = (ViewGroup) findViewById(R.id.root);
mImageView = (ImageView) mRrootLayout.findViewById(R.id.imageView);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150);
mImageView.setLayoutParams(layoutParams);
mImageView.setOnTouchListener(this);
}
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
view.setLayoutParams(layoutParams);
break;
}
mRrootLayout.invalidate();
return true;
}
}
Creating View layout activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_vertical_margin" >
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="124dp"
android:src="#drawable/ic_launcher" />
</RelativeLayout>

Change TextureView Size at Runtime

I am working on streaming a mp4 to a textureView for a app i am currently working on. i have the TextureView displaying the video however i need to resize it to match the screen size on rotation. After much trial and error it seems that the problem is that the TextureView cannot be made larger than the containing view. I have also tried to resize the container view but i am then unable to center the TextureView correctly on screen.
public void onOrientationChanged(int orientation) {
if(isLandscape(orientation)){
myTexture.setRotation(-90);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.width = height;
params.height = (height * 9)/16;
params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
myTexture.setLayoutParams(params);
myTexture.getLayoutParams().height = (height * 9)/16;
myTexture.getLayoutParams().width = height;
rl.requestLayout();
rl.invalidate();
rl.recomputeViewAttributes(myTexture);
Log.v("View Size", "Width tex: " + myTexture.getWidth());
Log.v("View Size", "Height tex: " + myTexture.getHeight());
Log.v("View Size", "Width tex parent: " + rl.getWidth());
Log.v("View Size", "Height tex parent : " + rl.getHeight());
}
<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=".MyActivity"
android:id="#+id/mediaParent"
android:layout_centerInParent="true"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp">
<TextureView
android:layout_width="360dp"
android:layout_height="203dp"
android:id="#+id/surface"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Try This link :
http://www.binpress.com/tutorial/video-cropping-with-texture-view/21
private void initView() {
mTextureView = (TextureView) findViewById(R.id.textureView);
// SurfaceTexture is available only after the TextureView
// is attached to a window and onAttachedToWindow() has been invoked.
// We need to use SurfaceTextureListener to be notified when the SurfaceTexture
// becomes available.
mTextureView.setSurfaceTextureListener(this);
FrameLayout rootView = (FrameLayout) findViewById(R.id.rootView);
rootView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_UP:
updateTextureViewSize((int) motionEvent.getX(), (int) motionEvent.getY());
break;
}
return true;
}
});
}
private void updateTextureViewSize(int viewWidth, int viewHeight) {
mTextureView.setLayoutParams(new FrameLayout.LayoutParams(viewWidth, viewHeight));
}

How can I give an imageview click effect like a button on Android?

I have imageview in my Android app that I am using like a button with the onClick event given, but as you might guess it is not giving imageview a clickable effect when clicked. How can I achieve that?
You can do this with a single image using something like this:
//get the image view
ImageView imageView = (ImageView)findViewById(R.id.ImageView);
//set the ontouch listener
imageView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
ImageView view = (ImageView) v;
//overlay is black with transparency of 0x77 (119)
view.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP);
view.invalidate();
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
ImageView view = (ImageView) v;
//clear the overlay
view.getDrawable().clearColorFilter();
view.invalidate();
break;
}
}
return false;
}
});
I will probably be making this into a subclass of ImageView (or ImageButton as it is also a subclass of ImageView) for easier re-usability, but this should allow you to apply a "selected" look to an imageview.
You can design different images for clicked/not clicked states and set them in the onTouchListener as follows
final ImageView v = (ImageView) findViewById(R.id.button0);
v.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.setImageBitmap(res.getDrawable(R.drawable.img_down));
break;
}
case MotionEvent.ACTION_CANCEL:{
v.setImageBitmap(res.getDrawable(R.drawable.img_up));
break;
}
}
return true;
}
});
The better choice is that you define a selector as follows
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="#drawable/img_down" />
<item android:state_selected="false"
android:drawable="#drawable/img_up" />
</selector>
and select the image in the event:
v.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
return true;
}
});
EDIT: Although the original answer below works and is easy to set up, refer to this post by an Android Developer Advocate at Google if you want / need a more efficient implementation. Also note that the android:foreground attribute is coming to all Views, including ImageView, by default in Android M.
The problem with using a selector for an ImageView is that you can only set it as the view's background - as long as your image is opaque, you will not see the selector's effect behind it.
The trick is to wrap your ImageView in a FrameLayout with the attribute android:foreground which allows us to define an overlay for its content. If we set android:foregroundto a selector (e.g.?android:attr/selectableItemBackground for API level 11+) and attach the OnClickListener to the FrameLayout instead of the ImageView, the image will be overlaid with our selector's drawable - the click effect we desire!
Behold:
<FrameLayout
android:id="#+id/imageButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:attr/selectableItemBackground" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/yourImageFile" />
</FrameLayout>
(Note this should be placed within your parent layout.)
final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view) {
// do whatever we wish!
}
});
Use style="?android:borderlessButtonStyle" in the XML file.
It will show the Android default click effect.
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"
style="?android:borderlessButtonStyle"
/>
Simply just use an ImageButton.
Here is my simple way to solve that:
ImageView iv = (ImageView) findViewById(R.id.imageView);
iv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//Agrega porcentajes de cada fraccion de grafica pastel
Animation animFadein = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_in);
iv.startAnimation(animFadein);
});
In file res/anim/fade_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" >
<alpha
android:duration="100"
android:fromAlpha="0.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
If you want ripple when tapped, it can be given by this code :
<ImageView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</ImageView>
Similarly, you can implement click effect for TextView
<TextView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</TextView>
Set the selectable background to the ImageView and add some padding. Then attach the OnClickListener.
<ImageView
android:id="#+id/your_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/your_image"
android:padding="10dp"
android:background="?android:attr/selectableItemBackground"/>
For defining the selector drawable choice
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="#drawable/img_down" />
<item android:state_selected="false"
android:drawable="#drawable/img_up" />
</selector>
I have to use android:state_pressed instead of android:state_selected
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed ="true"
android:drawable="#drawable/img_down" />
<item android:state_pressed ="false"
android:drawable="#drawable/img_up" />
</selector>
This worked for me:
img.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
((ImageView)v).setImageAlpha(200);
break;
}
case MotionEvent.ACTION_MOVE:
{
// if inside bounds
if(event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0 && event.getY() < v.getHeight())
{
((ImageView)v).setImageAlpha(200);
}
else
{
((ImageView)v).setImageAlpha(255);
}
break;
}
case MotionEvent.ACTION_UP:
{
((ImageView)v).setImageAlpha(255);
}
}
return true;
}
});
#Edit: As Gunhan said there will be backward compatibility problem with setImageAlpha method.
I used this method:
public static void setImageAlpha(ImageView img, int alpha)
{
if(Build.VERSION.SDK_INT > 15)
{
img.setImageAlpha(alpha);
}
else
{
img.setAlpha(alpha);
}
}
You could try with android:background="#android:drawable/list_selector_background"
to get the same effect as the "Add alarm" in the default "Alarm Clock" (now Desk Clock).
I do some similar things
See suitable for you or not
View Press Effect Helper:
usage : do some simple press effect like iOS
Simple Usage:
ImageView img = (ImageView) findViewById(R.id.img);
ViewPressEffectHelper.attach(img)
https://gist.github.com/extralam/7489370
In combination with all the answers above, I wanted the ImageView to be pressed and changed state but if the user moved then "cancel" and not perform an onClickListener.
I ended up making a Point object within the class and setting its coordinates according to when the user pushed down on the ImageView. On the MotionEvent.ACTION_UP I recording a new point and compared the points.
I can only explain it so well, but here is what I did.
// set the ontouch listener
weatherView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Determine what action with a switch statement
switch (event.getAction()) {
// User presses down on the ImageView, record the original point
// and set the color filter
case MotionEvent.ACTION_DOWN: {
ImageView view = (ImageView) v;
// overlay is black with transparency of 0x77 (119)
view.getDrawable().setColorFilter(0x77000000,
PorterDuff.Mode.SRC_ATOP);
view.invalidate();
p = new Point((int) event.getX(), (int) event.getY());
break;
}
// Once the user releases, record new point then compare the
// difference, if within a certain range perform onCLick
// and or otherwise clear the color filter
case MotionEvent.ACTION_UP: {
ImageView view = (ImageView) v;
Point f = new Point((int) event.getX(), (int) event.getY());
if ((Math.abs(f.x - p.x) < 15)
&& ((Math.abs(f.x - p.x) < 15))) {
view.performClick();
}
// clear the overlay
view.getDrawable().clearColorFilter();
view.invalidate();
break;
}
}
return true;
}
});
I have an onClickListener set on the imageView, but this can be an method.
You can Override setPressed in the ImageView and do the color filtering there, instead of creating onTouchEvent listeners:
#Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if(getDrawable() == null)
return;
if(pressed) {
getDrawable().setColorFilter(0x44000000, PorterDuff.Mode.SRC_ATOP);
invalidate();
}
else {
getDrawable().clearColorFilter();
invalidate();
}
}
Based on Mr Zorn's answer, I use a static method in my abstract Utility class:
public abstract class Utility {
...
public static View.OnTouchListener imgPress(){
return imgPress(0x77eeddff); //DEFAULT color
}
public static View.OnTouchListener imgPress(final int color){
return new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN: {
ImageView view = (ImageView) v;
view.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
view.invalidate();
break;
}
case MotionEvent.ACTION_UP:
v.performClick();
case MotionEvent.ACTION_CANCEL: {
ImageView view = (ImageView) v;
//Clear the overlay
view.getDrawable().clearColorFilter();
view.invalidate();
break;
}
}
return true;
}
};
}
...
}
Then I use it with onTouchListener:
ImageView img=(ImageView) view.findViewById(R.id.image);
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) { /* Your click action */ }
});
img_zc.setOnTouchListener(Utility.imgPress()); //Or Utility.imgPress(int_color_with_alpha)
It is very simple if you have a lot of images, and you want a simple onTouch effect, without any XML drawable and only one image.
Use an android.widget.Button, and set its background property to an android.graphics.drawable.StateListDrawable. This can all be done in XML, or programmatically. See the Custom Button section of the Form Stuff tutorial.
I create sample here, just change ImageView into ClickableImageView from your layout. Hope it help.
I think ImageButton is a better solution
<ImageButton
android:layout_width="96dp"
android:layout_height="56dp"
android:src="#mipmap/ic_launcher"
android:adjustViewBounds="true"
android:background="#android:color/transparent"
android:foreground="#drawable/selector" />
I have a more beauty solution if you use background images :)
public static void blackButton(View button){
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xf0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
break;
}
}
return false;
}
});
}
OR:
You can use this form, with Image Button.
Create file res/drawable/btn_video.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/image"
android:state_pressed="true" />
<item android:drawable="#drawable/ico2"
android:state_focused="true" />
<item android:drawable="#drawable/ico2" />
</selector>
And res/layout/activity_main.xml:
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageButton"
android:layout_gravity="center_horizontal"
android:onClick="eventImageBtn"
android:background="#drawable/btn_video"
android:adjustViewBounds="true"
android:scaleType="fitXY"
/>
Your image change with a click, and you can adjust with a linear layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/menu_item_background">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"
android:paddingLeft="#dimen/main_screen_side_padding" android:paddingRight="#dimen/main_screen_side_padding" android:paddingTop="#dimen/main_screen_side_padding" android:paddingBottom="#dimen/main_screen_side_padding"
android:background="#ffb3ff13" android:weightSum="10.00">
<LinearLayout android:layout_weight="2.50" android:background="#ff56cfcd" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" >
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageButton"
android:layout_gravity="center_horizontal"
android:onClick="eventImageBtn"
android:background="#drawable/btn_video"
android:adjustViewBounds="true"
android:scaleType="fitXY"
/>
</LinearLayout>
<LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" >
</LinearLayout>
<LinearLayout android:layout_weight="4.50" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ff8aa5ff">
</LinearLayout>
<LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" >
</LinearLayout>
<LinearLayout android:layout_weight="2.00" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ffff7d1a" >
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
Here's my solution, which, using "nineOldAndroids" library, supports old APIs too:
rootView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(final View v, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
v.setBackgroundResource(R.drawable.listview_normal);
ViewHelper.setAlpha(imageView, 1);
break;
case MotionEvent.ACTION_DOWN:
v.setBackgroundResource(0);
v.setBackgroundColor(getResources().getColor(R.color.listview_pressed));
ViewHelper.setAlpha(imageView, 0.75f);
break;
}
return false;
}
});
It assumes the rootView is the cell itself (the layout), and that it has a single imageView that you wish to be affected by the color that you wish to apply to the whole cell.
EDIT: if you wish, you can also extend ImageView to handle foreground, and set it to "?android:attr/selectableItemBackground". There is a library for this here and a tutorial on how to do it for any view you wish, here.
Thanks for the help on this thread. However, you missed one thing...you need to handle the ACTION_CANCEL as well. If you don't then you might not properly restore the alpha value of the ImageView in the event that a parent view in the view hierarchy intercepts a touch event (think a ScrollView wrapping you ImageView).
Here is a complete class that is based off the above class but takes care of the ACTION_CANCEL as well. It uses an ImageViewCompat helper class to abstract the differences in the pre-post JellyBean API.
public class ChangeAlphaOnPressedTouchListener implements OnTouchListener {
private final float pressedAlpha;
public ChangeAlphaOnPressedTouchListener(float pressedAlpha) {
this.pressedAlpha = pressedAlpha;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView iv = (ImageView) v;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ImageViewCompat.setAlpha(iv, pressedAlpha);
break;
case MotionEvent.ACTION_MOVE:
if (isInsideViewBounds(v, event)) {
ImageViewCompat.setAlpha(iv, pressedAlpha);
} else {
ImageViewCompat.setAlpha(iv, 1f);
}
break;
case MotionEvent.ACTION_UP:
ImageViewCompat.setAlpha(iv, 1f);
break;
case MotionEvent.ACTION_CANCEL:
ImageViewCompat.setAlpha(iv, 1f);
}
return false;
}
private static boolean isInsideViewBounds(View v, MotionEvent event) {
return event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0
&& event.getY() < v.getHeight();
}
}
Here is my code. The idea is that ImageView gets color filter when user touches it, and color filter is removed when user stops touching it.
Martin Booka Weser, AndrĂ¡s, Ah Lam, altosh, solution doesn't work when ImageView has also onClickEvent.
worawee.s and kcoppock (with ImageButton) solution requires background, which has no sense when ImageView is not transparent.
This one is extension of AZ_ idea about color filter.
class PressedEffectStateListDrawable extends StateListDrawable {
private int selectionColor;
public PressedEffectStateListDrawable(Drawable drawable, int selectionColor) {
super();
this.selectionColor = selectionColor;
addState(new int[] { android.R.attr.state_pressed }, drawable);
addState(new int[] {}, drawable);
}
#Override
protected boolean onStateChange(int[] states) {
boolean isStatePressedInArray = false;
for (int state : states) {
if (state == android.R.attr.state_pressed) {
isStatePressedInArray = true;
}
}
if (isStatePressedInArray) {
super.setColorFilter(selectionColor, PorterDuff.Mode.MULTIPLY);
} else {
super.clearColorFilter();
}
return super.onStateChange(states);
}
#Override
public boolean isStateful() {
return true;
}
}
usage:
Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
I tried with:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/get_started"
android:src="#drawable/home_started"
style="?android:borderlessButtonStyle"
android:adjustViewBounds="true"
android:clickable="true"
android:elevation="5dp"
android:longClickable="true" />
and this worked. Please note on the line: style="?android:borderlessButtonStyle"
I think the easiest way is creating a new XML file. In this case, let's call it "example.xml" in the drawable folder, and put in the follow code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/blue"
android:state_pressed="true" />
</selector>
But before that you have to set the colors in the colors.xml file, in the values folder, like this:
<resources>
<color name="blue">#0000FF</color>
</resources>
That made, you just set the Button / ImageButton to use the new layout, like this:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/example"
/>
Then when you click that image, it will change to the color set in
<item android:drawable="#color/blue"
android:state_pressed="true" />
giving the feedback that you want...
This is the best solution I ever seen. Its more generic.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" >
<alpha
android:duration="100"
android:fromAlpha="0.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
You can made a simple ripple effect for ImageView. This is great for icons.
In res/drawable create circular_shape.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#android:color/white"/>
</shape>
</item>
In res/drawable create a drawable res file ripple_effect_iv.xml:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item
android:id="#android:id/mask"
android:drawable="#drawable/circular_shape" />
</ripple>
Set it as background for ImageView also you can consider padding for showing ripple natural:
<ImageView
android:background="#drawable/ripple_effect_iv"
android:padding="10dp"/>
yes your ImageView become small but you can simply increase the android:layout_width and android:layout_height.
As for now, we should develop Material Design practice. In this case you could add a ripple effect on an ImageView.

Categories