get the position of a clicked button in Linear layout - android

So I am working on a linear layout where i add and remove Imagebuttons dynamically. So everytime an imagebutton is clicked and an action is taken, the imagebutton gets removed and changed with another imagebutton/s. The thing is i'd like to maintain the position of the clicked buttons so i can add a new imagebutton at the same location.
final ViewGroup.LayoutParams lpiv = iv.getLayoutParams();
il.removeView(iv);
int ilBtn = R.drawable.ta;
iv3.setImageResource(ilBtn);
iv5.setImageResource(ilBtn);
iv3.setClickable(false);
iv.setClickable(false);
il.addView(iv5, lpiv);
il.addView(iv3, lpiv);
//iv3.setLayoutParams(lpiv);

Correct me, but wouldnt it be easier just to change the image of the ImageButton instead
of adding a new button? To distinguish the status just check the image or a status variable.
customImageButton.setBackgroundResource(R.drawable.imageName);
this.status = this.NEW_STATUS;

Use LinearLayout.indexOfChild(View child) before you call remove, then call addView(View child, int index) with that index.

Is the code pasted in the question the body of your OnClickListener? If so, just modify it to do something like the following before you call removeView():
float originalX = view.getX();
float originalY = view.getY();
where view is the reference to the ImageButton that's being clicked, and then call setX() and setY() on your new buttons.
Just a heads-up, this will only work if the button being clicked and the ones being added are the same height and with. If they're not, you'll have to do some calculations based on the X/Y of the original one versus the height/width difference to find the same x,y point.

Related

Get the position of a view just after an addView()

Everything is in the title. I need to add the view at some point in my relativeLayout but not necessary at the OnCreate method. What I want to do is adding a view when the user click on the RelativeLayout, no problem for that. But I need to know the position of this view as soon as possible after I used addView method. Currently I'm using postDelayed but I need to put a high value to be sure that it is displayed before taking the position of the view. I tried using post but didn't work very well so that's why i use a delayed value. I also tried something with treeObserver some time ago but maybe i used it wrong I don't know because it did not work.
Edit:
Here I create the layout param.
RelativeLayout.LayoutParams laoutparam = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT );
laoutparam.addRule(RelativeLayout.CENTER_IN_PARENT);
Here I create my custom view and add the layoutparam to it:
Button button = (Button)findViewById(R.id.lol);
CustView view = new Bubble(getApplicationContext(), "Press this button", button);
bubble.setLayoutParams(laoutparam);
And then in the constructor of my custom RelativeLayout I do an addView(view).
Thanks for your help.
I hope this helps you with getting view location: https://www.tutorialspoint.com/how-to-get-the-absolute-coordinates-of-a-view-in-android
Example:
int loc[]=new int[2];
yourView.getLocationOnScreen(loc);
int x=loc[0];
int y=loc[1];

Using setLeft/setRight methods on new textview

I'm working with TextViews progammatically and I need to dynamically add new views and set their left/top position in the RelativeLayout parent.
What I'm doing is something like this:
RelativeLayout global=(RelativeLayout)findViewById(R.id.global);
TextView view=(TextView)findViewById(R.id.root);
RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final TextView childView=new TextView(view.getContext());
lp.addRule(RelativeLayout.ABOVE, view.getId());
childView.setLayoutParams(lp);
childView.setId(childView.getId()+1);
childView.setText("TRY STRING");
childView.setTextSize(view.getTextSize());
childView.setWidth(view.getWidth());
childView.setLeft(view.getLeft()+interval);
global.addView(childView);
Basically, I have a textview in a certain position (which is called view) and I'm trying to create a new textview above the existing one and on the same left position.
Although the getLeft() method correctly returns the left position of view, childView happens to have the left field set to zero, and appears at the left end of the screen when i add it to the RelativeLayout.
It looks like it's completely ignoring the setLeft method!
Can anyone explain why?
Thank you very much in advance!
public final void setLeft (int left)
Added in API level 11
Sets the left position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.
Parameters
left The bottom of this view, in pixels.
most likely the left value is being set by the layout every time it is drawn and overrides the value that you are setting on your view.
android layouts are very XML ish even when doing it programmatically.
try using
lp.setMargins(int left, int top, int right, int bottom);
..or some other method that won't be undone when the layout is drawn

Dynamically Setting RelativeLayout.LayoutParams.addRule

I have this issue where I have a relative layout that has two child relative layouts (leftpanel and rightpanel). They're inside a custom layout for listview items and each item is updated from a json response from the server. So the size depends on what the server provides.
Issue: I want to have each panel's height to match each other, but it seems that setting layout_height to match_parent doesn't work (actually, if this can be resolved, then no more problems).
What I did: I programmatically set the align top and bottom of each panel to each other -- if the other's bigger, adjust the other one and vice versa. So what I did was to have a view (rightpanel) to listen to rightPanel.getViewTreeObserver().addOnScrollChangedListener(), and call the method below everytime there's a scroll change:
private void updateLayoutAlignmentParams(ViewHolder viewHolder) {
RelativeLayout.LayoutParams leftPanelLayoutParams = (RelativeLayout.LayoutParams)viewHolder.leftPanel.getLayoutParams();
RelativeLayout.LayoutParams rightPanelLayoutParams = (RelativeLayout.LayoutParams)viewHolder.rightPanel.getLayoutParams();
int leftPanelHeight = viewHolder.leftPanel.getHeight();
int rightPanelHeight = viewHolder.rightPanel.getHeight();
if(leftPanelHeight > rightPanelHeight) {
rightPanelLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, 0);
rightPanelLayoutParams.addRule(RelativeLayout.ALIGN_TOP, 0);
leftPanelLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, viewHolder.rightPanel.getId());
leftPanelLayoutParams.addRule(RelativeLayout.ALIGN_TOP, viewHolder.rightPanel.getId());
} else {
leftPanelLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, 0);
leftPanelLayoutParams.addRule(RelativeLayout.ALIGN_TOP, 0);
rightPanelLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, viewHolder.leftPanel.getId());
rightPanelLayoutParams.addRule(RelativeLayout.ALIGN_TOP, viewHolder.leftPanel.getId());
}
}
What happens: not all the views get updated while scrolling; so I get a lop-sided listview item where one is bigger than the other vertically but some do adjust well. Odd thing is, when the item gets out of view, it's lop-sided, then gets corrected consistently.
Note: I also tried
addOnDrawListener() - every item is updated but I get an ArrayList out of bounds index but doesn't point to any line in my code. Wouldn't be the best solution anyway as I need to support devices with API < 16.
setOnGlobalLayoutListener() - Nothing happens.
Please let me know if you know why or have a better solution.
Finally [kindof] fixed it! Replaced the whole method with the code below:
private void updateLayoutAlignmentParams(ViewHolder viewHolder) {
viewHolder.rightPanel.setMinimumHeight(viewHolder.leftPanel.getHeight());
viewHolder.leftPanel.setMinimumHeight(viewHolder.rightPanel.getHeight());
}
Although, I was able to achieve having the left and right panel aligned with each other using the code above. I'm now having issues where the previous view's height and width are retained when I switch views. :(
Edit:
Okay, I ended up using LinearLayout to wrap the whole listview item. Not really sure why RelativeLayout isn't complying with match_parent, though.

How to change a header TextView Text when during scrolling of Horizontal scrollView?

I have a horizontal scroll view, I also have a relativelayout as it's child. I am adding child views of this relativelayout dynamically. I have a header text which should be update when I scroll according to respective child views. How can I do this because I am able to get the current focused item in horizontal scroll. Please give me some suggestion or examples which can be helpful for me, thanks..
You should specify an OnTouchListener for your HorizontalScrollView and in it's onTouch() method detect the type of MotionEvent and change your TextView's color to the appropriate
If you are creating this childs dinamically you can set a tag to them with the content you want to show in the header TextView.
//Creating RelativeLayout childs
TextView newChild = new TextView(this).
newChild.setTag(textToShowWhenThisItemIsFocused);
Then if you know which item is focused you just have to get the tag.
// "selected" is the focused view
header.setText((String) selected.getTag());
When to use the second code depends on your implementation. Since you didn't provide any code it's hard to know how to monitor the scroll, but i.e. you could control Touch Events and update the header when the user is moving his finger over the screen (you should also take into account the inertia after the user stops tapping).
EDIT: How to get the focused View
First of all, I barely have experience doing things like this, so I'm not sure if this is going to work or if there are better ways to do it. I'll just tell you the way I would approach this problem.
To be able to know the focused View you need to know the coordinates where this View should be. Since it's an horizontal ScrollView we will need the X coordinate. Since we want the View in the middle of the ScrollView I would do it like this:
private int centerSV;
private ScrollView mScrollView;
...
centerSV = mScrollView.getWidth()/2;
Now we have the center of the ScrollView. Now we need to know which child is in this position:
private int getFocusedChildId(){
for(int i=0; i<mChilds.length; i++){
int childLeftCoord = mChilds[i].getLeft() - mScrollView.getScrollX();
if(childLeftCoord <= centerSV && centerSV <= childLeftCoord + mChilds[i].getWidth())
return mChilds[i].getId();
}
// No view found in the center, maybe ScrollView wasn't full. Return the first one
return mChilds[0].getId();
}
Again, I'm not sure if this is going to work, it's just an idea of how to approach your issue. Also, you should take this into account:
getWidth() and getHeight() of View returns 0

How to bring a view to front without calling bringToFront()?

There is apparently a bug in Android which breaks View.bringToFront.
If I have Views arranged in a GridView and want to bring a View to front by calling bringToFront(), it may get moved to the bottom right position in the GridView.
Something shady is going on there, so I can't use bringToFront(). When I don't call it, everything works fine. But the Views overlap - if I use scale animation to scale up a View, it's partially obscured by the Views to the bottom and to the right.
I've checked out bringToFront's source and it calls parent.bringChildToFront(...)
it's this method
public void bringChildToFront(View child) {
int index = indexOfChild(child);
if (index >= 0) {
removeFromArray(index);
addInArray(child, mChildrenCount);
child.mParent = this;
}
}
it apparently removes the View from itself! Without mercy! Is a ViewGroup so dumb that it can't manage Z-indexes in any other way that shuffling controls around? Obviously when GridView removes its child and then adds it back again, it gets placed at the end of the Grid!
Is there anything I can do to show a View on top of others without resorting to some hacking? One thing that comes to my mind is to create another View above the GridView, which will appear to be above the one I'm trying to bringToFront(), but I don't like this solution.
apparently I missed the android:clipChildren="false" property in GridView. It solves my problem.
Have you tried making the View focusable and just calling requestFocus()?
Calling bringToFront() changes the ordering in the GridView. Try creating an ImageView with an image of the view you want to animate and animate that instead.
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
final ImageView imageView = new ImageView(getActivity());
imageView.setImageBitmap(bitmap);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(view.getWidth() , view.getHeight());
imageView.setLayoutParams(params);
rootview.addView(imageView);
Add an animation listener to your animation and remove the ImageView at the end of the animation.
From API 21 you can call:
view.setZ(float)
If you target API above 21, you can simply add the attribute android:translationZ="xxx dp" to your XML.
Please note that if you add elevation in views like cardview, you go into the Z axis. And if you want a view come to foreground using this way, you just have to make it higher than the elevation you set.
Example : 6 dp elevation in cardview will require a 7dp in the attribute translationZ of the view you want foreground.

Categories

Resources