Is there an onImageChangedListener() on a ImageView?
I need the event when the image is changed from the ImageView.
There is no default listener in Android .. but we can create the imagechange listiner .. copy the class and instead of using ImageView use MyImageView..
public class MyImageView extends ImageView {
private OnImageChangeListiner onImageChangeListiner;
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public void setImageChangeListiner(
OnImageChangeListiner onImageChangeListiner) {
this.onImageChangeListiner = onImageChangeListiner;
}
#Override
public void setBackgroundResource(int resid) {
super.setBackgroundResource(resid);
if (onImageChangeListiner != null)
onImageChangeListiner.imageChangedinView(this);
}
#Override
public void setBackgroundDrawable(Drawable background) {
super.setBackgroundDrawable(background);
if (onImageChangeListiner != null)
onImageChangeListiner.imageChangedinView(this);
}
public static interface OnImageChangeListiner {
public void imageChangedinView(ImageView mImageView);
}
}
Check the imageview code in grepcode. You don't know when it is changed or redrawn. It is because after you setImageDrawable(), imageview will invalidate. At this time, the image IS NOT CHANGED correctly until ondraw is called.
Anyway, why do you want to know the onimagechangedlistener?
If you want to load the image from network and check change in imageview you can use imageView.isAttachedToWindow(). I have tried downloading the image from network and disabled the progressbar after image downloaded and attached to window.
Use,
if(imageView.isAttachedToWindow()){
//your code here
}
Related
I'm making a custom button which is designed to handle onClick events internally. Here's a simplified version of my implementation:
public class CustomButton extends Button implements View.OnClickListener {
public CustomButton(Context context) {
super(context);
setOnClickListener(this);
}
#Override
public void onClick(View v) {
setText("Clicked!");
}
}
No surprises in the above code! The problem is that the activity/fragment/whatever containing the button could call setOnClickListener(View) which would prevent the onClick(View) method inside the button from receiving the onClick event, thus changing the function of my button in an undesirable way. I though about overriding setOnClickListener(View) to throw an exception if the argument is not this, but I don't want to prevent the button from having external listeners, I just want to add an internal feature.
Which method of Button if any can I override to do extra stuff when the button is clicked without taking away the ability of other classes to listen to onClick events? Basically, which method in Button dispatches OnClick events?
I thought of a solution. I made CustomButton as follows:
public class CustomButton extends Button implements View.OnClickListener {
private OnClickListener externalOnClickListener;
public CustomButton(Context context) {
super(context);
super.setOnClickListener(this);
}
public CustomButton(Context context, AttributeSet attrs) {
super(context, attrs);
super.setOnClickListener(this);
}
public CustomButton(Context context, AttributeSet attrs, int defStyleAttrs) {
super(context, attrs, defStyleAttrs);
super.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// Do all of my stuff
setText("Clicked!");
setBackground(Color.GREEN);
// Pass onClick event to external listener
if (externalOnClickListener != null) {
externalOnClickListener.onClick(v);
}
}
#Override
public void setOnClickListener(OnClickListener l) {
externalOnClickListener = l;
}
}
Basically setOnClickListener() is overriden so that it just stores the passed listener as an instance variable. At construction, the button sets itself as its own on click listener, so that it can receive the on click events, do something, then pass the event on to the stored listener.
i would like to create a class, which extends Button and implement a method, which is alwasy called, when the Button is clicked. But i still want it's OnClickListener to be called.
My Idea is to save the OnClickListener into a private member when the constructor or setOnClickListener is called and then set the OnClickListener to my own OnClickListener. This one would then call my method and the saved OnClickListener.
But i don't see how i can get the OnClickListenr, i only see, how to set it.
Is there a way to acces it?
Or do you have a better idea? (it doesn't matter wheter my method is called before or after the OnClickListener)
I guess you could do this:
public class OnceClickedTwiceRunButton extends Button{
public OnceClickedTwiceRunButton(Context context) {
super(context);
}
public OnceClickedTwiceRunButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OnceClickedTwiceRunButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private OnClickListener extraClickMethod;
#Override
public void setOnClickListener(OnClickListener newListener)
{
super.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
DefaultClickMethod(v);
if(extraClickMethod != null)
{
extraClickMethod.onClick(v);
}
}
});
extraClickMethod = newListener;
}
private void DefaultClickMethod(View v)
{
//TODO
}
}
I have a View that needs to detect when it's being attached to its parent view.
In a ViewGroup I have the OnHierarchyChangeListener which allows me to know when a child view is being added / removed, but I need the opposite thing.
You can create custom view and do your stuff in its onAttachedToWindow
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.d("CustomView", "onAttachedToWindow called for " + getId());
Toast.makeText(getContext(), "added", 1000).show();
}
}
[EDIT 1]
you can ensure that your customview added to correct viewgroup which you want
#Override
protected void onAttachedToWindow() {
// TODO Auto-generated method stub
super.onAttachedToWindow();
if(((View)getParent()).getId()== R.id.relativelayout2)
{
Log.d("CustomView","onAttachedToWindow called for " + getId());
Toast.makeText(context, "added", 1000).show();
}
}
Solution without having to create a custom view
If the View is one you can't or don't want to modify, you can use View.addOnAttachStateChangeListener to get hooks when the view is attached to the view hierarchy and when it is detached from the view hierarchy.
Something like:
Kotlin
view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
// Do stuff when view has been attached to window
}
override fun onViewDetachedFromWindow(v: View) {
// Do stuff when view has been detached from window
}
})
Java
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
#Override
public void onViewAttachedToWindow(View v) {
// Do stuff when view has been attached to window
}
#Override
public void onViewDetachedFromWindow(View v) {
// Do stuff when view has been detached from window
}
});
If you are using kotlin you can use doOnAttach extension function on View.
view.doOnAttach {
// TODO: Your view has a parent, you can use it now.
(view.parent as ViewGroup)?.yourAction()
}
Well, you have the view in OnHierarchyChangeListener, so I would suppose that you could add a callback to your views (by subclassing them with an interface) and call it from OnHierarchyChangeListener. This way, your views will be called at the same time that the OnHierarchyChangeListener is called.
However, I won't be surprised that when this happens, that many properties of your views like their dimensions might not be defined yet.
I think if you need that kind of control it may be best to make it a fragment. That way you get access to a much more granular lifecycle.
You can look at this problem in a different angle, if you monitor the parents for attached views by implementing method onViewAdded.
Example:
public class LayoutInvokeChildAdded extends RelativeLayout {
private OnDoneListener onDoneListener;
public LayoutInvokeChildAdded(Context context) {
super(context);
}
public LayoutInvokeChildAdded(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LayoutInvokeChildAdded(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onViewAdded(View child) {
super.onViewAdded(child);
if (onDoneListener != null)
onDoneListener.onDone(childe);
}
public void setOnDoneListener(OnDoneListener onDoneListener) {
this.onDoneListener = onDoneListener;
}
}
I am running a frame by frame animation using sequential images in a surface view. I am declaring the activity by :
public class myView extends SurfaceView implements SurfaceHolder.Callback
{
public myView (Context paramContext, Listener paramListener)
{
super(paramContext);
getHolder().addCallback(this);
//Some Code
}
public void doDraw(Canvas paramCanvas, int imgpos)
{
// Animation from image source using InputStream
}
public boolean onTouchEvent(MotionEvent paramMotionEvent)
{
return super.onTouchEvent(paramMotionEvent);
}
public void surfaceChanged(SurfaceHolder paramSurfaceHolder, int paramInt1, int paramInt2, int paramInt3)
{
//Some Code
}
public void surfaceCreated(SurfaceHolder paramSurfaceHolder)
{
//Some code
}
public void surfaceDestroyed(SurfaceHolder paramSurfaceHolder)
{
//Some Code
}
}
Now I am trying to implement a Listener for the Animation End event for the above using the following code :
public static abstract interface Listener
{
public abstract void onAnimationEnd();
}
I am stuck up with the above code and can anyone suggest me how I can implement this interface in another activity, so that I can find out that the current animation is over in the Surface View Activity.
Thanks in Advance,
Tim
Add
setAnimationListener
to your animation. If you are assign the animation in the form of drawable in xml file check here to know how to get the animation drawable.
I cant seem to find an event that listens for playback state. I am mostly interested in the play/pause state. I am using MediaController which has a Play/Pause button, but I have a secondary button that also controls Play/Pause. Using my custom button, I can play/pause, but if I play/pause using the MediaController play/pause button, I currently have no way to change the image on my custom play/pause button to either play or pause.
Is there an event that I do not know about so I can do some work during play/pause?
This is a very similar question: How to catch event when click pause/play button on MediaController
If you're using the MediaController in combination with a VideoView, it should be relatively easy to extend the latter and add your own listener to it.
The custom VideoView would then look something like this in its most basic form:
public class CustomVideoView extends VideoView {
private PlayPauseListener mListener;
public CustomVideoView(Context context) {
super(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomVideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setPlayPauseListener(PlayPauseListener listener) {
mListener = listener;
}
#Override
public void pause() {
super.pause();
if (mListener != null) {
mListener.onPause();
}
}
#Override
public void start() {
super.start();
if (mListener != null) {
mListener.onPlay();
}
}
public static interface PlayPauseListener {
void onPlay();
void onPause();
}
}
Using it is identical to using a regular VideoView, with the only difference being that we can now hook up our own listener to it.
// Some other code above...
CustomVideoView cVideoView = (CustomVideoView) findViewById(R.id.custom_videoview);
cVideoView.setPlayPauseListener(new CustomVideoView.PlayPauseListener() {
#Override
public void onPlay() {
System.out.println("Play!");
}
#Override
public void onPause() {
System.out.println("Pause!");
}
});
cVideoView.setMediaController(new MediaController(this));
cVideoView.setVideoURI(...);
// or
cVideoView.setVideoPath(...);
// Some other code below...
Finally, you may also declare it in your xml layout and inflate it (as shown above) - just make sure your use <package_name>.CustomVideoView. Example:
<mh.so.CustomVideoView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/custom_videoview" />
You should be able to set your own MediaController.MediaPlayerControl and override pause and start