I've been trying to get the position from a button inside a dialog so that i can use it to place a button below that button in the activity.
I've tried a few things but none of them seem to work
int loc1[] = new int[2];
button.getLocationInWindow(loc1);
int loc2[] = new int[2];
button.getLocationOnScreen(loc2);
I've also tried
button.getX();
button.getY();
The button was never placed below the button in the dialog.
(I should note that i only mentioned the methods to get the postiion)
Can anybody help me ?
Thanks !
You need to wait for the callback when the Button has placed. The code you are using not returning the proper value because the value is returned before the Button is placed. So add the Button in a layout with height/width as wrap_content and Use this code:
layout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
int[] locations = new int[2];
layout.getLocationOnScreen(locations);
int x = locations[0];
int y = locations[1];
}
});
Make layout params, they depend on the parent, so you should probably use LinearLayout.LayoutParams or RelativeLayout.LayoutParams (there are other cases).
And add layout_below(button1) to your LayoutParams object. And set that LayoutParams to new button you want to appear below first button1.
Related
I have an activity window (Activity pic), when I click the second button, popup window appears at the bottom (it's good, I need that) of screen (PopUp pic), when i click on the edit text field, brings up the keyboard, but it cover the popup window edit text fields (Keyboard 3).
Where is my error that the popup window does not up when the keyboard appears? Do you have any ideas?
Screen shoots
Activity
PopUp
Keyboard
Pop-Up Window class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_insert);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
getWindow().setLayout((int)(width),(int)(height*.4));
WindowManager.LayoutParams params = getWindow().getAttributes();
params.gravity = Gravity.BOTTOM;
getWindow().setAttributes(params);
PopupWindow popup = new PopupWindow(
popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
/** ... **/
popup.showAtLocation(this, Gravity.CENTER, 0, 0);
Then the only thing you need is a Listener for the Keyboard (or more general: For Window Height changes). This was actually easier than I thought - and it didn't require any special access like an Activity-object or similar. Even in my independent View-class which only knows the Context (which I didn't want to cast), I was able to accomplish that. Everything you need is only one View-object which has already been added to the layout.
final View root = this.getRootView();
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
Rect r = new Rect();
root.getWindowVisibleDisplayFrame(r);
// Calculate the difference between the original height and the new height
int heightDiff = r.height() - root.getHeight();
// Now update the Popup's position
// The first value is the x-axis, which stays the same.
// Second value is the y-axis. We still want it centered, so move it up by 50% of the height
// change
// The thir`enter code here`d and the fourth values are default values to keep the width/height
popup.update(0, heightDiff / 2, -1, -1);
}
});
What I am trying to do is programmatically creating a row of buttons with a constraint view.
I am creating two buttons and I want to have them next to each other without doing something to the .xml file, since the number of buttons can vary depending on the user.
I want to use something like (this code is part of an Activity):
ConstraintLayout layout = findViewById(R.id.layout);
Button btn1 = new Button(this);
Button btn2 = new Button(this);
ConstraintLayout.LayoutParams params1 = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT,ConstraintLayout.LayoutParams.WRAP_CONTENT);
ConstraintLayout.LayoutParams params2 = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT,ConstraintLayout.LayoutParams.WRAP_CONTENT);
layout.addView(btn1, 1, params1);
params2.topToTop = btn1.getId();
params2.leftToRight = btn1.getId();
layout.addView(btn2, 2, params2);
Setting the two params2 values does not work because apparently I cannot really access the ID of button1.
What would be a working solution to this?
Things I have read and tried:
Using tags instead of ids
Accessing the buttons using an ArrayList of all the created buttons as a private member for the Activity
Giving some random id (that I have chosen) to the Views using setId()
Using something like this works, because I have predefined that btn3 in the xml file:
params2.topToTop = layout.findViewById(R.id.btn3).getId();
params2.leftToRight = layout.findViewById(R.id.btn3).getId();
But in all the other cases my btn2 just lands on top of btn1 (or rather on the top left edge of the layout)
Thank you in advance!
You can use the following method to generate view id programmatically:
private static final AtomicInteger nextGeneratedId = new AtomicInteger(10000);
public static int generateViewId() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
for (;;) {
final int result = nextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 10000; // Roll over to 10000, not 0.
if (nextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
} else {
return View.generateViewId();
}
}
call .setId(generatedId) for the buttons you create.
I have this function which is supposed to create an array of TextViews with unique ids.
Each TextView is supposed to perform a unique action, however when any one of them is clicked, they perform the function of the last TextView .
(ie, anyone of them appends a 9 to the last TextView the way this i set up) Do you know why it does this, and how I can fix it?
Any help would be greatly appreciated.
//Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_what_can_imake);
int textViewCount = 10;
TextView[] textViewArray = new TextView[textViewCount];
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.myLayout);
for(int i = 0; i < textViewCount; i++) {
textViewArray[i] = new TextView(this);
textViewArray[i].setText("Title"+Integer.toString(i));
textViewArray[i].setPadding(8,8+50*i,8,0);
textViewArray[i].setId(i);
LayoutParams myTitleDimensions = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
textViewArray[i].setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
int myId = v.getId();
((TextView) v).append(Integer.toString(myId));
}
});
myLayout.addView(textViewArray[i],myTitleDimensions);
}
}
You are using different paddingTop to layout your TextViews vertically:
textViewArray[i].setPadding(8,8+50*i,8,0);
this makes the TextViews visually separate to each other, but in fact they are all overlapped, the 2nd one overlapped the 1st, the 3rd one overlapped the 2nd, etc. At last, the 9th one overlapped all, so no matter which text you clicked, you actually clicked the 9th one.
To fix this, you should change the way you layout the TextViews.
For example, use RelativeLayout.addRule(int verb, int anchor):
RelativeLayout.LayoutParams myTitleDimensions = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (i > 0) {
myTitleDimensions.addRule(RelativeLayout.BELOW, i - 1);
}
By the way, 0 is not a valid id, so your 1st TextView will be still overlapped by the 2nd one, just change the way to generate ids a little.
Here's an image of what my issue looks like:
That box at the bottom is the top half of a button. Whenever I've got too many Stock Options in the dialog box, it first forces the button off screen, THEN it scrolls.
I want the button fixed at the bottom of the dialog and then have the scrolling happen.
Here's the code:
public void buyStock(View view){
Context context = getApplicationContext();
//create ScrollView to hold everything
ScrollView scrollView = new ScrollView(context);
//generate content for dialog
LinearLayout dialogContainer = new LinearLayout(context);
dialogContainer.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 400, 1);
dialogContainer.setLayoutParams(params);
dialogContainer.setPadding(15, 15, 0, 15);
dialogContainer.setBackgroundColor(Color.WHITE);
//each hotel stock options
for (int i = 0; i < hotels.size(); i++) {
Hotel testHotel = hotels.get(i);
testHotel.setPrice(200);
View stockPicker = getStockPicker(testHotel);
LinearLayout.LayoutParams pickerParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 100, 1.0f);
pickerParams.gravity = Gravity.LEFT;
stockPicker.setLayoutParams(pickerParams);
dialogContainer.addView(stockPicker);
stockPicker.setBackgroundColor(0xffffff);
}
scrollView.addView(dialogContainer);
LinearLayout dialogLayout = new LinearLayout(context);
dialogLayout.setOrientation(LinearLayout.VERTICAL);
Button buyButton = new Button(context);
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 100);
buyButton.setLayoutParams(buttonParams);
LinearLayout buttonLayout = new LinearLayout(context);
buttonLayout.addView(buyButton);
dialogLayout.addView(scrollView);
dialogLayout.addView(buttonLayout);
ContextThemeWrapper ctw = new ContextThemeWrapper(this, R.style.AppTheme);
AlertDialog.Builder buyStockDialog = new AlertDialog.Builder(ctw);
buyStockDialog.setTitle("Buy Stock: ");
buyStockDialog.setView(dialogLayout);
buyStockDialog.show();
}
Make dialogLayout a RelativeLayout, and then declare buttonParams as a RelativeLayout.LayoutParams (layout params are declared according the parent viewgroup type, which for buyButton is now a RelativeLayout). Your also going to need to declare a RelativeLayout.LayoutParams for scrollView.
note: This code is in c#/monodroid, not raw java/android, so some quick porting of some of the methods and constants may need to be required, but shouldn't be too time consuming.
If this doesn't work out exactly trying experimenting with other combinations of the RelativeLayout position rules and/or gravity. Let me know if it doesn't work out.
RelativeLayout.LayoutParams scrollParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, some_height);
RelativeLayout.LayoutParams buttonParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, 100);
Then, add these statements to control where scrollView and buyButton are positioned
scrollParams.AddRule(LayoutRules.AlignParentLeft);
scrollParams.AddRule(LayoutRules.AlignParentTop);
buttonParams.AddRule(LayoutRules.Below, scrollView.Id);
The for the getting the button on the bottom of the screen, try one of two things
buttonParams.AddRule(LayoutRules.AlignParentBottom);
or
buyButton.Gravity = Gravity.BOTTOM
Try explicitly setting a fixed height to the scrollView
scrollView.LayoutParameters.Height = HEIGHT;
I think it defaults to WRAP_CONTENT if not specified, and is why its scaling.
You may have to set it in a layout file if you cant from code
<ScrollView
android:id="#+id/scroll_view_1
android:layout_width="wrap_content"
android:layout_height="100"/>
and then change
ScrollView scrollView = new ScrollView(context);
to
ScrollView scrollView = findViewById(R.Id.scroll_view_1, this);
Try wrapping the scrollView in another LinearLayout, and set this new layout's height to a fixed width that keeps the button low enough to your liking. You can actually replace the Scrollview with a ListView, but don't do this until after at least trying to get this fix working first. ListViews scroll, but you'd still face this problem without this fix.
To fix the new issue you mentioned below (with some quick and dirty code, you should use trial and error to fix it correctly), try the following
//each hotel stock options
for (int i = 0; i < hotels.size(); i++)
{
// ...
}
if( hotels.size() < numberOfItemsNeededForCorrectView )
{
for( int i=0; i < numberOfItemsNeededForCorrectView - hotels.size(); i++ )
{
View blankView = new View(context);
LinearLayout.LayoutParams viewParams = new LinearLayout.LayoutParams(1, 100);
blankView.setLayoutParams(viewParams);
blankView.setViewState(ViewState.INVISIBLE);
dialogContainer.addView(stockPicker);
}
}
You can try replacing your scrollView with a list view still and see if that fixes things. You can also try tweaking layout and gravity settings until you get it, or trying introducing other layouts or reorganizing your layouts (or using RelativeLayout, its really not that bad).
So, now in 2022 I've also had this problem. I've just set fixed size for ScrollView in fragment layout xml-file. When you have this problem, you can set, for example, 150dp or 200dp and be happy! And for more convenience, you can create special layout for landscape screen orientation and set fixed layout_height size there. I'm really confused that there's no information about this problem besides this page on the Internet.
<ScrollView
android:layout_width="match_parent"
android:layout_height="200dp">
<!--your view into scrollView here-->
</ScrollView>
I'm making an app exclusively for android tablets and part of it has buttons dynamically created based on various news headlines. I have a single dimens.xml and I use the scaling factor from DisplayMetrics to make the sizes appropriate for different densities. The problem is that when I change the size in my xml it has absolutely no effect on the dimension that the method returns.
RelativeLayout.LayoutParams announcementButtonLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
announcementButtonLayout.topMargin = topMargin;
announcementButtonLayout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
announcementButtonLayout.height = this.getResources().getDimensionPixelSize(R.dimen.news_button_height);
announcementButtonLayout.width = getResources().getDimensionPixelSize(R.dimen.dashboard_right_width);
Button button = new Button (this.getActivity());
button.setWidth(getResources().getDimensionPixelSize(R.dimen.dashboard_right_width));
button.setBackgroundResource(R.drawable.photo_edited);
button.setTextColor(getResources().getColor(R.drawable.news_poll_item_text_color));
float f =Utilities.getPixelScaleMultiplier();
f *= getResources().getDimension(R.dimen.news_item_text);
button.setTextSize(f);
button.setText(announcement.getDescription());
button.setMaxLines(1);
button.setTag(announcement);
button.setOnClickListener(this);
button.setLayoutParams(announcementButtonLayout);
button.setId(index);
Based on my button code above, what could be causing this breach of trust?
Thanks,
Adurnari
EDIT: Included my LayoutParams as reference
Found the solution:
"Cleaning" was taking the values that I had changed in my xml and adding them on a later portion of the page where they were located previously. The lower ones were dictating the size.
Try to work with button.setBounds
Use LayoutParams to set view width and height, then add it to viewgroup.
Button button = new Button (this.getActivity());
//button.setWidth(getResources().getDimensionPixelSize(R.dimen.dashboard_right_width));
button.setBackgroundResource(R.drawable.photo_edited);
button.setTextColor(getResources().getColor(R.drawable.news_poll_item_text_color));
float f =Utilities.getPixelScaleMultiplier();
f *= getResources().getDimension(R.dimen.news_item_text);
button.setTextSize(f);
button.setText(announcement.getDescription());
button.setMaxLines(1);
button.setTag(announcement);
button.setOnClickListener(this);
LayoutParams announcementButtonLayout = new LayoutParams(getResources().getDimensionPixelSize(R.dimen.dashboard_right_width), LayoutParams.WRAP_CONTENT);
button.setLayoutParams(announcementButtonLayout);
button.setId(index);
Clean the project after changing dimens.xml value, maybe the R file is not getting updated in your case.