I'm using an inflater to show a popup setting menu made by me. It's composed by some images and buttons. After complete XML layout I'm started to code it, it opens correctly with this code:
public void Settings_button(View view)
{
if (p != null)
showPopup(Main_activity.this, p);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
int[] location = new int[2];
ImageButton setting_button = (ImageButton) findViewById(R.id.settings_button);
// Get the x, y location and store it in the location[] array
// location[0] = x, location[1] = y.
setting_button.getLocationOnScreen(location);
//Initialize the Point with x, and y positions
p = new Point();
p.x = location[0];
p.y = location[1];
}
// The method that displays the popup.
private void showPopup(final Activity context, Point p) {
Resources r = getResources();
int popupWidth = 500;
int popupHeight = 300;
// Inflate the popup_layout.xml
LinearLayout viewGroup = (LinearLayout) context.findViewById(R.id.popup);
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.settings_popup_layout, viewGroup);
// Creating the PopupWindow
final PopupWindow popup = new PopupWindow(context);
popup.setContentView(layout);
popup.setWidth(popupWidth);
popup.setHeight(popupHeight);
popup.setFocusable(true);
// Some offset to align the popup a bit to the right, and a bit down, relative to button's position.
int OFFSET_X = 150;
int OFFSET_Y = 30;
// Displaying the popup at the specified location, + offsets.
popup.showAtLocation(layout, Gravity.NO_GRAVITY, p.x + OFFSET_X, p.y + OFFSET_Y);
}
But now I need to get ImageViews IDs and Buttons IDs, I've used:
//In onCreate of Main_Activity
ImageView popup_setting_1_icon;
popup_setting_1_icon = (ImageView) findViewById(R.id.setting_1_icon);
Button popup_setting_1_button;
popup_setting_1_button = (Button) findViewById(R.id.setting_1_button);
But when I'm starting to use this Views for example popup_setting_1_icon.setImageResource(R.id.setting_done_icon); I get application crash with NullPointerException.
I've read something like I should get pointers from inflater but I've tried to do so inside showPopup method but nothing. How I can solve this problem?
Initialize views in show popup method:
ImageView popup_setting_1_icon;
popup_setting_1_icon = (ImageView)layout. findViewById(R.id.setting_1_icon);
Button popup_setting_1_button;
popup_setting_1_button = (Button)layout. findViewById(R.id.setting_1_button);
I had a very similar problem with programmatically inflating a container and populating it. This is what worked for me:
LayoutInflater inflator = LayoutInflater.from(getContext());
LinearLayout viewGroup = (LinearLayout) getActivity().findViewById(
R.id.popup);
View layout = inflator.inflate(R.layout.settings_popup_layout, null);
Button button = (Button) layout.findViewById(R.id.setting_1_button);
ImageView image = (ImageView) layout.findViewById(R.id.setting_1_icon);
//bind data to view/buttons
viewGroup.addView(layout);
This is assuming your settings button and image views are inside the settings popup layout.
Related
I need to show popup window directly above button. My button is placed inside scroll view, and popup always shown below button. Here is my code:
private void showPopup(View view, String text) {
if (infoPopup == null) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View popupView = layoutInflater.inflate(R.layout.popup_credit_request_passport, null);
TextView tvPopupText = popupView.findViewById(R.id.tv_popup_text);
tvPopupText.setMovementMethod(new ScrollingMovementMethod());
tvPopupText.setText(text);
FrameLayout flBackground = popupView.findViewById(R.id.fl_background);
flBackground.setBackground(new BubbleDrawable(getContext(), R.color.azure, 16, 16, 8));
infoPopup = new PopupWindow(popupView,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
infoPopup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
infoPopup.setOutsideTouchable(true);
infoPopup.showAtLocation(view, Gravity.TOP, (int) view.getX(), (int) view.getY());
} else {
dismissInfoPopup();
}
}
But it is not work. Please hep me.
Change Gravity to Top and reset your coordinates according to your requirement.
infoPopup.showAtLocation(view, Gravity.TOP, 0, (int) view.getY());
When you have to show the popup, find out the location of the button in the screen, then use the showAtLocation() method as Prachi Said using Gravity.TOP and the x,y coordinates of the button on screen...
I have an EditText inside of a RelativeLayout (named TopLayout in code below) that is inside of a ListView. There is TextWatcher on the EditText that changes the height of the RelativeLayout (and ListView). But when the height changes, the cursor inside of the EditText moves to the beginning.
Is there anyway to get it to stay where it is?
public void setItemHeight(int itemPos, int itemHeight) {
if (mChallengingThoughtsListView != null) {
View itemView = mChallengingThoughtsListView.getChildAt(itemPos);
LinearLayout topLayout = itemView.findViewById(R.id.TopLayout);
// Set item height
ViewGroup.LayoutParams params = topLayout.getLayoutParams();
params.height = itemHeight;
topLayout.setLayoutParams(params);
// TODO: Put code to place cursor back where it was
}
}
I,ve got a gridview that gets 4 imageviews from an adapter, i want to have them 2x2 resized and fitted on my screen.
here´s the code for that:
#Override
protected View createQuizContentView() {
mAnswerView = new GridView(getContext());
StateListDrawable selector = new StateListDrawable();
selector.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(Color.LTGRAY));
selector.addState(new int[]{-android.R.attr.state_pressed}, new ColorDrawable(Color.WHITE));
mAnswerView.setSelector(selector);
//mAnswerView.setSelector(R.drawable.selector_button);
mAnswerView.setNumColumns(2);
mAnswerView.setAdapter(new OptionsQuizAdapter(getQuiz().getOptions(),
R.layout.imgitem_answer));
mAnswerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mAnswered = position;
allowAnswers(mAnswerView,position);
}
});
return mAnswerView;
}
and
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(mLayoutId, parent, false);
}
final ImageView imageView;
String text = getText(position);
Context context = parent.getContext();
Resources resources = context.getResources();
String stripped = text.replace("-", "");
final int resourceId = resources.getIdentifier(stripped, "drawable",
context.getPackageName());
Drawable d = ContextCompat.getDrawable(context, resourceId);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int height = size.y;
double dviewheight = height/3.32;
int viewheight = (int)dviewheight;
imageView = (ImageView) convertView;
imageView.setPadding(64, 64, 64, 64);
convertView.setLayoutParams(newGridView.LayoutParams(GridView.AUTO_FIT, viewheight));
imageView.setImageDrawable(d);
return imageView;
}
At the moment i´am setting the height of the imageview inside the gridview by getting the screensize and dividing it which works fine on most device resolution but i still would prefer a more dynamic solution that would work if i added more rows to the gridview.
This is how it looks:
Screensize/magic number
When i use GridView.AUTO_FIT on the height it will add a lot of useless space and i get a scrollbar on the right like this:
Useless space vertically
I have tried several configurations and stretches but none seems to work. Any way to achieve what i want programmatically without xml?
Try this:
gridView.setNumColumns(2);
My code works only for visible views.
mGridView = (GridView) findViewById(R.id.gridView);
mGridView.setAdapter(new ButtonAdapter(this, list));
Method called when chronometer ticks:
public void setBackground(int i) {
Button button = (Button) mGridView.getChildAt(i);
button.setBackgroundResource(R.drawable.button_shape);
This method causes NPE because getChildAt cannot access non-visible childs.
I tried some solutions found here but no luck so far (android - listview get item view by position - this solution did not causes NPE but was changing background for more buttons in one tick)
What I need is to change first button background on first tick, second button on second tick.. and last button on last tick and stay consistent while scrolling.
My getView method in ButtonAdapter:
public View getView(final int position,
View convertView, ViewGroup parent) {
Button btn;
LayoutInflater inflater = LayoutInflater.from(mContext);
if (convertView == null) {
// if it's not recycled, initialize some attributes
btn = (Button) inflater.inflate(R.layout.button, parent, false);
int width = mContext.getResources().getDimensionPixelSize(R.dimen.gridView_param_width);
int height = mContext.getResources().getDimensionPixelSize(R.dimen.gridView_param_height);
GridView.LayoutParams params = new GridView.LayoutParams(width, height);
btn.setLayoutParams(params);
} else {
btn = (Button) convertView;
}
btn.setText(list.get(position).getName());
btn.setId(position);
btn.setTag(position);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SetGridViewListener activity = (SetGridViewListener) mContext;
activity.onClickGridView(position);
Button btn = (Button)v;
btn.setBackgroundResource(R.drawable.button_shape_clicked);
btn.setClickable(false);
}
});
return btn;
}
I think my problem is in getView method which is probably not recycling well for my purpose.
Thanks in advance.
I have solved it already. I used ViewHolder pattern like here ListView subobject clickable confilct and this method to access buttons from my activity:
public View getViewByPosition(int pos, GridView gridView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition ) {
return gridView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return gridView.getChildAt(childIndex);
}
}
(android - listview get item view by position)
If you would like my concrete solution, write in comment and I will add it.
This is my code:
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout viewGroup = (LinearLayout) findViewById(R.id.layout_popup);
final View layout = layoutInflater.inflate(R.layout.popup_layout,viewGroup);
final PopupWindow popup = new PopupWindow(GameActivity.this);
Point popupSize = new Point(getResources().getDimensionPixelSize(R.dimen.popup_width),getResources().getDimensionPixelSize(R.dimen.popup_height));
popup.setContentView(layout);
popup.setWidth(popupSize.x);
popup.setHeight(popupSize.y);
popup.setFocusable(true);
File dir = getFilesDir();
File temp = new File(dir.getPath()+"/temp.prj");
try {
if(!temp.exists())temp.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
File[] filesArray = dir.listFiles();
ArrayList<String> files = new ArrayList<>();
for(File file:filesArray)
{
files.add(file.getName());
}
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
popup.showAtLocation(layout, Gravity.NO_GRAVITY, (size.x-popupSize.x)/2, (size.y-popupSize.y)/2);
ListView listView = (ListView)layout.findViewById(R.id.listViewDir);
final EditText fileName = (EditText)layout.findViewById(R.id.editTextFilename);
final StableArrayAdapter adapter = new StableArrayAdapter(GameActivity.this,R.layout.list_item, files);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
final TextView item = (TextView) view;
fileName.setText(item.getText());
}
});
The bit that is causing me trouble is:
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
final TextView item = (TextView) view;
fileName.setText(item.getText());
}
Where after I have clicked on the item in the list view, I then go to click on the filename view and the exception
android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W#53668b30 is not valid; is your activity running?
is thrown. I have tried running fileName.setText(item.getText()); on the UI thread, I have tried using MainActivity.this (or my variant of it, GameActivity.this) in numerous different places. Nothing seems to be working. Does anyone have any idea what's going wrong? All related questions seem to revolve around a Dialog rather than a Popup
UPDATE
For some unearthly reason, adding android:inputType="textNoSuggestions" to the EditText fileName in xml stops the exception. I only noticed this after prefixing the items in the listview with a number (which means they don't get spellchecked). It looks like someone else ran into a similar error Android ICS spelling error correction causes PopupWindow to crash and they too do not have an answer