Hi so I'm trying to get the location of an imageview in android using
xPosition = view.getLeft();
yPosition = view.getTop();
But it keeps returning 0 no matter where the imageview happens to be. The same also occurs when using
view.getLocationOnScreen(int[] location);
Does anybody have any ideas why this might be?
You can use those methods after onCreate has completed. One way to do it is this inside the onCreate method is this:
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
//do your thnig here.....
if (Build.VERSION.SDK_INT < 16) {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
else {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
The globalLayoutListener will be notified when the layout is built and run the onGlobalLayout method. Be sure to remove the globalLayoutListener after you do what you want to do.
Related
Edit: I'm trying to get the height/width of a view, so that I can programmatically put some ImageView into it. However getHeight() and getWidth() returns 0 so I was not able to put the ImageView into the correct positions. I did make the ImageView appear on the RelativeView (main_activity) though.
I'm aware of the answer related the getHeight() returning 0 error: How to retrieve the dimensions of a view? Unfortunately it's gives me exception on the line with ld.setLayerInset(), saying I'm trying to invoke the method on a null pointer reference. I' aware of the meaning of such an exception, but I don't understand what's wrong with my code as I was just trying to copy and paste the codes on the above link to my codes with amendments on the variable names. Here are some of my codes:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.activity_main).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
LayerDrawable ld = (LayerDrawable) findViewById(R.id.activity_main).getBackground();
ld.setLayerInset(1,0,0,0,0);
if (Build.VERSION.SDK_INT >= 16) {
findViewById(R.id.activity_main).getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
findViewById(R.id.activity_main).getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
...
}
I think the problem occurs on getBackground() getting null then cause the next line to throw exception, but I don't know what's the problem at all.
View's size is not related to its background at all. A view can have a non zero size without having a background (hopefully !). You do not have to carry of the view's bg.
Then a detail, the findViewById(int) method can be a really heavy call, you should call it once.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View mainView = findViewById(R.id.yourViewId)
mainView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
// At this stage of layout, if your view is well positioned, its width and height aren't zero
int width = mainView.getWidth();
int height = mainView.getHeight();
// Do whatever you want with view's size here
if (Build.VERSION.SDK_INT >= 16) {
mainView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
mainView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
...
}
I'm interested in what is the right and first possible moment to get size of first item of RecyclerView?
I've tried to use:
recyclerView.setLayoutManager(new GridLayoutManager(context, 2));
recyclerView.setAdapter(new MyDymmyGridRecyclerAdapter(context));
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
recyclerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
View firstRecyclerViewItem = recyclerView.getLayoutManager().findViewByPosition(0);
// firstRecyclerViewItem is null here
}
});
but it returns null at this moment.
If you're using OnGlobalLayoutListener you should remember onGlobalLayout can be called multiple times. Some of those calls can happen even before Layout is ready (and by ready I mean the moment when you can get dimensions of a View by calling view.getHeight() or view.getWidth()). So the proper way of implementing your approach would be:
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int width = recyclerView.getWidth();
int height = recyclerView.getHeight();
if (width > 0 && height > 0) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
recyclerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
View firstRecyclerViewItem = recyclerView.getLayoutManager().findViewByPosition(0);
}
});
Apart from that you still need to be sure that at the time of findViewByPosition(0) call:
Your RecyclerView's Adapter has at least one data element.
View at position 0 is currently visible in RecyclerView
Tell me if that fixes your issue, if not there is still another way of doing what you need.
In my extended RecyclerView I override onChildAttachedToWindow like this
#Override
public void onChildAttachedToWindow(View child) {
super.onChildAttachedToWindow(child);
if (!mIsChildHeightSet) {
// only need height of one child as they are all the same height
child.measure(0, 0);
// do stuff with child.getMeasuredHeight()
mIsChildHeightSet = true;
}
}
I had this type of problem. I want to perform click by default on the first visible position of the recylerview. I wrote the code for that on onResume but it did not work. I solved my problem by writting the code in onWindowFocusChanged method
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(isCalledForTheFirstTime)
{
LinearLayoutManager manager= (LinearLayoutManager) rcViewHeader.getLayoutManager();
int pos= manager.findFirstCompletelyVisibleItemPosition();
View view=manager.findViewByPosition(pos);
if(view!=null)
{
view.performClick();
}
// change the vaule so that it would not be call in case a pop up appear or disappear
isCalledForTheFirstTime=false;
}
}
For the above emulator, in my onCreate method, how to get the size(height and width) of area of the white space? (not including the Project1 Screen2' space)?
Initialize the view and call this method in on create method
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
//now we can retrieve the width and height
int width = view.getWidth();
int height = view.getHeight();
//... //do whatever you want with them //... //this is an important step not to keep receiving callbacks: //we should remove this listener //I use the function to remove it based on the api level!
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} });
im trying to measure a ImageView, after my fragment is displayed, or if possible before.
I heared, that its not yet possible in the onActivityCreated. But somehow it works with the global Layout listener. -But how? -I have a method, wich measures and does some code, i just don't know when to call the method.
Can somebody gice an example?
the beginning of the measure method:
public void skalierung() {
InputStream dots=getResources().openRawResource(R.drawable.amountofdots);
Bitmap dotsBmp = BitmapFactory.decodeStream(dots);
View mainframe=(View)getActivity().findViewById(R.id.mainframe);
int breite=mainframe.getWidth();
Thanks!
To set a GlobalLayoutListener you have to get ViewTreeObserverof your View using the view.getViewTreeObserver() method which :
Returns the ViewTreeObserver for this view's hierarchy. The view tree observer can be used to get notifications when global events, like layout, happen.
After doing that well , you can addOnGlobalLayoutListener on your ViewTreeObserever
OnGlobalLayoutListener : Interface definition for a callback to be invoked when the global layout state or the visibility of views within the view tree changes.
and inside the onGlobalLayoutmethod you can call the getWidth on the your desired view, here's an example :
View mainframe=(View)getActivity().findViewById(R.id.mainframe);
ViewTreeObserver vto = mainframe.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
skalierung(); // here you can call the getWidth and getHeight methods
ViewTreeObserver obs = mainframe.getViewTreeObserver();
// you have to reset the ViewTreeObserver each time to ensure the reuse of the OnGlobalLayoutListener
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
Hope it helps.
what i'm trying to do sounds really simple. Resize my GridView when SoftKeyboard is open. Put it back on place(resize height) where it belongs if SoftKeyboard dissapears.
For this i did following:
root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
if(gv != null && searchbar != null) {
root.getWindowVisibleDisplayFrame(r);
if(screenHeight > r.bottom) {
RelativeLayout.LayoutParams myLayoutParams = (android.widget.RelativeLayout.LayoutParams) gv.getLayoutParams();
myLayoutParams.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
gv.setLayoutParams(myLayoutParams);
int gvHeight = screenHeight - r.bottom - searchbar.getLayoutParams().height;
gv.getLayoutParams().height = gvHeight;
}else {
RelativeLayout.LayoutParams myLayoutParams = (android.widget.RelativeLayout.LayoutParams) gv.getLayoutParams();
myLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
gv.setLayoutParams(myLayoutParams);
}
}
}
});
Where gv is my GridView. If i start my app, and click in my searchbar, the softkeyboard appears and this method is firing all the time.(Even if the layout isn't changing or even that i don't click anything). Therefore it blocks my UI. Did i do something wrong?
Also, does someone have a better idea implementing this function.(Resizing my Grid when Softkeyboard appears and vice versa).
Any help is appreciated.
Notice
Working with onFocusChange sounds not good to me. Because on my device. I can Close the SoftKeyboard with a backPress without loosing Focus
Have you tried using View.OnLayoutChangeListener available for API 11+ instead?
Otherwise you have to remove the listener when it fires after checking for a large enough height difference (see this). Don't forget to add the listener back in any click listener that fires up the keyboard.
#Override
public void onGlobalLayout() {
int heightDiff = root.getRootView().getHeight() - root.getHeight();
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
root.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
... rest of your code
}
}