android.view.WindowManager$BadTokenException list view set text then focus - java

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

Related

Add item to a specific column in ListView Adapter

I have an increment system and I want when onClick to save value from DialogAlert in a column in ListView Adapter.
Here is my Adapter:
public class VanzatorProduseList extends ArrayAdapter<VanzatorProduse> {
private Activity context;
private SparseBooleanArray selectedListItemsIds;
private List<VanzatorProduse> vanzatorProduseList;
public VanzatorProduseList(Activity context, List<VanzatorProduse> vanzatorProduseList){
super(context, R.layout.list_produse_vanzator, vanzatorProduseList);
this.context = context;
selectedListItemsIds = new SparseBooleanArray();
this.vanzatorProduseList = vanzatorProduseList;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list_produse_vanzator, null, true);
TextView textViewProdus1 = (TextView) listViewItem.findViewById(R.id.textViewProdus1);
TextView textViewPret1 = (TextView) listViewItem.findViewById(R.id.textViewPret1);
final TextView textViewCantitate1 = (TextView) listViewItem.findViewById(R.id.textViewCantitate1);
final VanzatorProduse vanzatorProduse = vanzatorProduseList.get(position);
textViewProdus1.setText(vanzatorProduse.getProdus());
textViewPret1.setText(vanzatorProduse.getPret());
textViewCantitate1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.dialog_alert);
dialog.setTitle("Alege Canitatea");
// set the custom dialog components - text, image and button
final Button dialogBtn = (Button) dialog.findViewById(R.id.dialog_btn);
final ElegantNumberButton elegantNumberButton = (ElegantNumberButton) dialog.findViewById(R.id.elegantNumberButton);
// if button is clicked, close the custom dialog
dialogBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
dialog.dismiss();
}
});
dialog.show();
}
});
return listViewItem;
}
Here is what I tried but I got an error and no idea what to do next :
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
Error:
'add(com.dev.darius.neglije.Vanzator.ListaProduse.VanzatorProduse)' in 'java.util.List' cannot be applied to '(java.lang.String)'
Here I'm stuck I want to display in TextView called textViewCantitate1.
Hope you understand.
As stated in earlier answers by #jibrahim:
You are trying to add String type into List vanzatorProduseList. You can add only VanzatorProduse type into vanzatorProduseList list. So, the cause of the problem is:
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
You need to do something like this Create Object of your Custom class and assign value to that:
String num = elegantNumberButton.getNumber();
VanzatorProduse numVanProObject = new VanzatorProduse();
numVanProObject .setNumber(num );
vanzatorProduseList.add(numVanProObject );
But your custom call should have method to cater this type issue
Edit: Do not forget to call notifyDataSetChanged() method to refresh the list
VanzatorProduse producse = new VanzatorProduse();
producse.setProdus("add value here")
vanzatorProduseList.add(producse);
You are trying to add String type into List<VanzatorProduse> vanzatorProduseList. You can add only VanzatorProduse type into vanzatorProduseList list. So, the cause of the problem is:
String num = elegantNumberButton.getNumber();
vanzatorProduseList.add(num);
In your code you have following lines:
final VanzatorProduse vanzatorProduse = vanzatorProduseList.get(position);
textViewProdus1.setText(vanzatorProduse.getProdus());
textViewPret1.setText(vanzatorProduse.getPret());
So, might be you add num value into vanzatorProduse.setProdus(num) or any other appropriate field and then add it into the list:
vanzatorProduseList.add(vanzatorProduse);

Error: java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2

How to remove the seperator line in footerLayout? I have a footerLayout below the listView, used to display the totalAmount as shown below. If I click the seperator line in footerLayout, my app crashed.
My MainActivity
AllAdapter obj = new AllAdapter(getApplication(), search, listview,imageView,text,button);
footerLayout = (LinearLayout) getLayoutInflater().inflate(R.layout.under_listview, null);
totalAmount = (TextView) footerLayout.findViewById(R.id.amount);
LogCat error
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
at com.example.tony.monthlyexpenses.adapter.AllAdapter.getItem(AllAdapter.java:61)
at com.example.tony.monthlyexpenses.QuickExpenses$1.onItemClick(QuickExpenses.java:88)
at android.widget.AdapterView.performItemClick(AdapterView.java:301)
The error pointed to listView onClickListener
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view, final int position, long id) {
mClickedPosition = position;
Expenses o = (Expenses) obj.getItem(position);
String day = o.getDate();
}
});
AllAdapter
public Expenses getItem(int position) {
return search.get(position);
}
The footerLayout is supposed to be displayed outside the listView, not inside. How can I get rid of this ?
I also have activity_main.xml, AllAdapter class, all_adapter.xml for ListView and also under_listview.xml for the footerLayout.
activity_main
AllAdapter
under_listview
How to move the footerLayout out from the ListView ?
I add android:footerDividersEnabled="false" now become like this
But still clickable !!!
The footerLayout is supposed to be displayed outside the listView, not
inside.
Actually, the footer is also part of the ListView and it adds up to the number of items the list has. Neverhteless, there are a few approaches how to ignore the click events on a footer view.
One option is instead of adding your view using:
addFooterView(footerLayout);,
use:
addFooterView(footerLayout, null, false);
The third parameter specifies whether the footer view should be selectable or not.
Another option would be to ignore the click when the position parameter is bigger than the size of your adapter dataset:
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view, final int position, long id) {
if(position < adapter.getCount()){
Expenses expenses = (Expenses) adapter.getItem(position);
String day = expenses.getDate();
}
}
});
Try to set the following line in your listview.
android:footerDividersEnabled="false"
I change this code and it works fine now.
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view, final int position, long id) {
Expenses o = (Expenses) listView.getAdapter().getItem(position);
if(o != null){
mClickedPosition = position;
//Expenses o = (Expenses) obj.getItem(position);
String day = o.getDate();
}
}
});
just a quick tutorial, if you are new to custom ListViewAdapters.
I would have an Object Expense like this:
class Expense {
Date date = new Date();
Double spendMoney = 5.0;
Bitmap image;
...
/** Continue with POJO **/
}
and an expenses_list_item.xml layout. (if you need help with that, i can add it later...)
In my MainActivity I would have an ArrayList<Expense> expensesList
and my custom ArrayListAdapter would look something like this:
class expenseListAdapter extends ArrayAdapter<Expense> {
expenseListAdapter() {
super(context, R.layout.expenses_list_item, expensesList);
}
#Override
public View getView(int pos, View view, ViewGroup parent) {
if (view == null) {
view = getActivity().getLayoutInflater().inflate(R.layout.list_item_series, parent, false);
}
ShowListItem current = expensesList.get(pos);
TextView expens = (TextView) view.findViewById(R.id.expenseText);
expens.setText(current.getSpendMoney());
... (all other needed values of your Expense object)
return view;
}
}
And finally, I could just set
ArrayAdapter<Expense> adapter = new expenseListAdapter();
expenseListView.setAdapter(adapter);
That would be it. Maybe a little bit complicated on the first look, but this method is very powerfull. If you need help, don't be afraid to ask ;)
Greets
Malik

Gridlayout with 2x2 imageview android

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);

CursorAdapter Listview recycling wrong

I created the following CursorAdapter which shows messages from my SQL database, everything is added well until I scroll the list, I know that the objects are recycled, but in a wrong way. Here is my CursorAdapter class:
public class ChatAdapter extends CursorAdapter {
public ChatAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.chat_item, parent,
false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView left = (TextView) view.findViewById(R.id.lefttext);
TextView right = (TextView) view.findViewById(R.id.righttext);
LinearLayout rightBubble = (LinearLayout) view
.findViewById(R.id.right_bubble);
LinearLayout leftBubble = (LinearLayout) view
.findViewById(R.id.left_bubble);
TextView leftDate = (TextView) view.findViewById(R.id.leftdate);
TextView rightDate = (TextView) view.findViewById(R.id.rightdate);
// Extract properties from cursor
String from = cursor.getString(cursor.getColumnIndexOrThrow("from"));
String txt = cursor.getString(cursor.getColumnIndexOrThrow("message"));
String date = cursor.getString(cursor.getColumnIndexOrThrow("t"));
String id = cursor.getString(cursor.getColumnIndexOrThrow("id"));
// Parse time
long datevalue = Long.valueOf(date) * 1000;
Date dateformat = new java.util.Date(datevalue);
String convert = new SimpleDateFormat("HH:mm").format(dateformat);
// Populate fields with extracted properties
if (from.equals("me")) {
right.setText(txt);
left.setText("");
rightBubble
.setBackgroundResource(R.drawable.balloon_outgoing_normal);
leftBubble.setBackgroundDrawable(null);
rightDate.setText(convert);
leftDate.setVisibility(View.GONE);
}
else {
left.setText(txt);
right.setText("");
leftBubble
.setBackgroundResource(R.drawable.balloon_incoming_normal);
rightBubble.setBackgroundDrawable(null);
leftDate.setText(convert);
rightDate.setVisibility(View.GONE);
}
}
}
Unfortenately, after scrolling the list, dates from the rightDate and leftDate dissapears after moving back. I think it't due the .setVisibility(View.GONE)
Any suggestions to fix this?
when the view is recycled, it is in the previous state, android did not clear the status for you.
To fix your problem, you have to set the view in question to VISIBLE when needed
Edit:
like this, add the 2 lines
if (from.equals("me")) {
// your original code
rightDate.setVisibility(View.VISIBLE); //add this
}
else {
// your original code
leftDate.setVisibility(View.VISIBLE); //add this
}

How to change background of non-visible buttons in GridView (Button adapter) from an activity

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.

Categories

Resources