Hi all I have a problem in displaying image in ImageView when clicked, i made a function to display whenever the image was click I have already added the android:onClick="drops" in .xml in every imageview of my sample game, i used gridlayout(3x3) with 9 imageview
here is the code of the function.
fun drops(view: View){
val imageView = ImageView(this)
var player = 0;
if (player == 0){
imageView.setImageResource(R.drawable.yellow)
imageView.animate().alpha(1f).rotation(360f).setDuration(600)
player == 1
}else {
imageView.setImageResource(R.drawable.red)
imageView.animate().alpha(1f).rotation(360f).setDuration(600)
player == 0
}
}
I'm unsure in what class is this function contained, I suppose it is either in a Fragment or Activity. As you said, you're binding the image views with drops method in the xml layout.
What could be the problem is this line:
val imageView = ImageView(this)
From your question we cannot see which class is this method defined in, so expression this could be anything. You might me instantiating an ImageView from the whole Activity or Fragment object, and cannot work in way you would like to. So I suggest to rewrite this line to something like this:
val imageView = view as ImageView
The function drops receives a single View parameter, which is the image view the user clicked - but View class has no method called setImageResource, so you need to cast it to the desired subtype (ImageView is subclass of View). This should do the job.
Related
I am trying to create a progress bar that will display while an image is downloading from a server. This image is loaded into a custom view. (I need it to be custom because I draw on the image.)
My solution was to add the custom view into the XML under the layout of the fragment, and mark its visibility as Visibility.GONE. This worked in the XML editor, as the progress bar took up the full space. Invisible did not work as it's position was still displayed.
The issue comes when the image path is given to my custom view. It would seem that setting Visibility.GONE on a view means that the view is not measured. But I need the dimensions of the view to measure how large the bitmap should be.
// Create the observer which updates the UI.
val photoObserver = Observer<String?> { photoPath ->
spinner.visibility = View.GONE
thumbnailFrame.visibility = View.VISIBLE
thumbnailFrame.invalidate()
thumbnailFrame.setImage(photoPath)
Looking at the Logs from the custom view, it is calling onMeasured() but it is doing it too late. I need onMeasure() to be called before setImage(). Is there a better way of handling this and if not is there a way to force the code to wait until I know the view has finished its measuring process?
Solved using a basic listener pattern with an anonymous class inline. I'm not sure if there is a better way but this way works just fine. Delay is not much of an issue since the view draws quite fast anyways.
* Set a listener to notify parent fragment/activity when view has been measured
*/
fun setViewReadyListener(thumbnailHolder: ViewReadyListener) {
holder = thumbnailHolder
}
interface ViewReadyListener {
fun onViewSet()
}
private fun notifyViewReadyListener() {
holder?.onViewSet()
}
spinner.visibility = View.INVISIBLE
thumbnailFrame.visibility = View.VISIBLE
//We have to make sure that the view is finished measuring before we attempt to put in a picture
thumbnailFrame.setViewReadyListener(object : ThumbnailFrame.ViewReadyListener {
override fun onViewSet() {
thumbnailFrame.setImage(photoPath)
//If we have a previous saved state, load it here
val radius = viewModel.thumbnailRadius
val xPosit = viewModel.thumbnailXPosit
val yPosit = viewModel.thumbnailYPosit
if (radius != null) {
thumbnailFrame.setRadius(radius)
}
if (xPosit != null) {
thumbnailFrame.setRadius(xPosit)
}
if (yPosit != null) {
thumbnailFrame.setRadius(yPosit)
}
}
})
}
I have a logo view, which is a full screen fragment containing single ImageView.
I have to perform some operations after the logo image is completely visible.
Following code is used to invoke the special task
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ImageView logoImageMaster = new ImageView(getContext());
//logoImageMaster.setImageResource(resID); //even after removing this, i am getting the callback twice
try {
// get input stream
InputStream ims = getActivity().getAssets().open("product_logo.png");
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
logoImageMaster.setImageDrawable(d);
}
catch(IOException ex) {
}
logoImageMaster.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() { //FIXME get called twice. Check this out, no info to distinguish first from second
// Log.e("PANEL", "onGlobalLayout of Logo IV ---------------------------------");
activityInterface.doSpecialLogic();
}
});
return logoImageMaster;
}
My exact problem is, onGlobalLayout is called twice for this view hierarchy.
I know that onGlobalLayout is invoked in performTraversal of View.java hence this is expected.
For my use case of Single parent with Single child view, I want to distinguish the view attributes such that doSpecialLogic is called once[onGlobalLayout is called twice] , after the logo image is completely made visible.
Please suggest some ideas.
OnGlobalLayoutListener gets called every time the view layout or visibility changes. Maybe you reset the views in your doSpecialLogic call??
edit
as #Guille89 pointed out, the two set calls cause onGlobalLayout to be called two times
Anyhow, if you want to call OnGlobalLayoutListener just once and don't need it for anything else, how about removing it after doSpecialLogic() call??
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
//noinspection deprecation
logoImageMaster.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
logoImageMaster.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
activityInterface.doSpecialLogic();
It seems to be called one time for each set done over the imageView
logoImageMaster.setImageResource(resID);
logoImageMaster.setImageDrawable(d);
You should Try using kotlin plugin in android
This layout listener is usually used to do something after a view is measured, so you typically would need to wait until width and height are greater than 0. And we probably want to do something with the view that called it,in your case
Imageview
So generified the function so that it can be used by any object that extends View and also be able to access to all its specific functions and properties from the function
[kotlin]
inline fun <T: View> T.afterMeasured(crossinline f: T.() -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (measuredWidth > 0 && measuredHeight > 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
f()
}
}
})
}
[/kotlin]
Note:
make sure that ImageView is described properly in the layout. That is its layout_width and layout_height must not be wrap_content. Moreover, other views must not result in this ImageView has 0 size.
I have the following scenario:
In a layout, I have imageviews aligned horizontally and vertically as shown in image.
First, which layout should be used for this purpose? RelativeLayout or FrameLayout? ListView inside the layout?
Also, instead of writing setOnClickListener for every imageview, how can I write just one click listener to get the clicked imageview?
A GridView is perfect for this. For more information on GridView, look here.
As for your onClickListener question: there is no easy way to do this, but what you can do is something like this:
Have an array containing every ImageView id like so:
public static final int[] IMAGE_VIEWS = {R.id.imageView1, R.id.imageView2, R.id.imageView3 /*etc*/}; //Make sure to list from the first imageview to the last image view in correct order
Define an onClickListener
private View.OnClickListener imageViewListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < IMAGE_VIEWS.length; i++) {
if (v.getId() == IMAGE_VIEWS[i]) {
doSomethingWithImageViewClick(i); //if ImageView 4 was clicked, variable 'i' will be 3 (because arrays start at index = 0).
}
}
}
}
Set the onClickListeners for all your imageViews:
final ImageView view1 = (ImageView) view.findViewById(R.id.imageView1);
view1.setOnClickListener(imageViewListener);
//etc
Use 'GridView' in the layout and use 'setOnItemClickListener' to handle click events,
You can find more details in below link
GridView.
GridView can achieve the effect. I think you can look at this Grid View.
I basically made a class, with this method:
void setResource(Context context, R.id resourceID) {
ImageView test = (ImageView) context.findViewById(resourceID);
}
The "findViewById" gives me a can't resolve method.
I have three ImageViews defined in XML, I would like to set the image associated to them programatically. in my main_activty I do so by using:
ImageView blah = (ImageView) this.findViewById(R.id.blah);
Then:
blah.setImageResource(R.drawable.pony);
HOWEVER, I would like to pass everything to my class I made and have it handle all that in the custom class, but when I try to pass everything (the code at the very top; "setResource") I get that findViewByID can't resolve method. Is there a way to do it that way?
I think you are trying to find the words to express what you are trying to do, and with some of the basic concepts. This is my best guess of what you are trying to accomplish...
The code below takes an id for drawable, loads it, and then puts it into an imageView in your layout. The ImageView must already be there in your layout, it does not create one for you dynamically.
void setResource(Context context, int resourceId) {
//resourceId = R.drawable.ponies (example)
Drawable drawable = context.getResources().getDrawable(resourceId);
//R.id.main_imageview is example imageView in a layout.
ImageView iv = findViewById(R.id.main_imageview);
iv.setImageDrawable(drawable);
}
I have a fullscreen view flipper on the galaxy tab containing two relative layouts, each of which is displaying between five and ten image views.
I am having problems when I try to slide one of the view flipper viewso ut and the other in, the "animation" does nothing and then just switches.
If I remove all but one of the image views in each of the view flipper children the animation is fine.
Can I somehow force it to use a mixed down version of the image for the animation, or is the relative layout container causing the performance problem?
There should be nothing going on at the time the flipper animation occurs so I can't understand the problem.
Thanks
EDIT: Some of the problematic code: Perhaps this might indicate areas causing the performance problems?
I have in my onClick, two method calls, used for switching backwards through the views and forward. A view is "generated" immediately before being added to the flipper and switched.
so, on the click of the back button (for example) I have (amongst other things) ....
nextView = new RelativeLayout(this);
makeAView(selectedViewObjects, viewHolder2);
switchViewNow(-1);
currentView = nextView;
...
private void makeAView(ViewObjects vObjects, RelativeLayout nextView)
{
for(Object obj : vObjects.viewObjects)
{
if(obj instanceof Image)
{
addImageView(nextView, obj);
{
else
{
if(obj instanceof Anim)
{
addAnimView(nextView, obj);
}
}
Where Image is a custom View implementation for displaying a static image and Anim is a custom view implementation for displaying an AnimationDrawable (multiframe image cycle).
Next we have the switch method:
private void switchViewNow(int direction)
{
if(direction == -1)
{
viewFrame.setInAnimation(AnimClass.inFromLeftAnimation(null));
viewFrame.setOutAnimation(AnimClass.outToRightAnimation(null));
viewFrame.showNext();
}
else
if(direction == 1)
{
viewFrame.setInAnimation(AnimClass.inFromRightAnimation(null));
viewFrame.setOutAnimation(AnimClass.outToLeftAnimation(null));
viewFrame.showNext();
}
}
I could be wrong, but it looks to me like you have overloaded nextView in a confusing way.
It is defined outside of makeAView, but makeAView expects a parameter which it names nextView.
You are passing viewHolder2 as nextView to this function.
This means that makeAView will NOT change the 'global' nextView, it will change viewHolder2.
But then you seem to assume that the 'global' nextView has been modified because you use it to assign currentView.
I think it would be a good place to start if you assign unique names to these two versions of nextView.
I wonder if you are even still looking for a solution: this post is rather old and ignored.