Last item click null pointer excepction - android

listView=(ListView)findViewById(R.id.list);
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View viewItem, int position, long arg3) {
if(!itemClicked)
{
viewItem = parent.getChildAt(position);
((Button)viewItem.findViewById(R.id.gov)).setVisibility(View.VISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.VISIBLE);
viewItem.invalidate();
itemClicked=true;
clickedItemPos=position;
TextView text = (TextView)viewItem.findViewById(R.id.item);
ime = text.getText();
}
else
{
viewItem=parent.getChildAt(clickedItemPos);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.INVISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.INVISIBLE);
viewItem = parent.getChildAt(position);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.VISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.VISIBLE);
viewItem.invalidate();
clickedItemPos=position;
TextView text = (TextView)viewItem.findViewById(R.id.item);
ime = text.getText();
}
final int[] coordAndCat = FavoriteCoord(ime.toString());
Nullpointer exception happens when I have more elements and when you scroll and click the last item on the listview. How to workaround this?
Note: I'm trying to display 2 buttons in every item that is being clicked. This code works for all clicks on items besides the last one (if there are many elements in the list and you need to scroll)

clickedItemPos isn't defined after else unless clickedItemPos=position has been called earlier. What line does the error happen on?

listView=(ListView)findViewById(R.id.list);
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View viewItem, int position, long arg3) {
if(!itemClicked)
{
viewItem = parent.getChildAt(position);
//start >> This might be where your problem is (R.id.gov)
((Button)viewItem.findViewById(R.id.gov)).setVisibility(View.VISIBLE);
//end <<
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.VISIBLE);
viewItem.invalidate();
itemClicked=true;
clickedItemPos=position;
TextView text = (TextView)viewItem.findViewById(R.id.item);
ime = text.getText();
}
else
{
viewItem=parent.getChildAt(clickedItemPos);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.INVISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.INVISIBLE);
viewItem = parent.getChildAt(position);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.VISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.VISIBLE);
viewItem.invalidate();
clickedItemPos=position;
TextView text = (TextView)viewItem.findViewById(R.id.item);
ime = text.getText();
}
final int[] coordAndCat = FavoriteCoord(ime.toString());
I think you said R.id.gov instead of R.id.go unless R.id.gov is truly an id you have. That is the only thing I saw 'wrong', please show a stacktrace for the error next time, it would help in debugging =)
EDIT
is clickedItemPos initialized somewhere else? because if it isn't this line: viewItem=parent.getChildAt(clickedItemPos); in your else statement would probably be null if nothing was selected before. I understand you want to use this in order to check for previously clicked items, but if nothing was clicked before, this will never get set to a value and therefore be null try doing this in that else statement to avoid the possible null variable:
else
{
if(clickedItemPos != null){ //only add this if there was a previous clicked item
viewItem=parent.getChildAt(clickedItemPos);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.INVISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.INVISIBLE);
viewItem = parent.getChildAt(position);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.VISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.VISIBLE);
viewItem.invalidate();
clickedItemPos=position;
TextView text = (TextView)viewItem.findViewById(R.id.item);
ime = text.getText();
}else{
viewItem = parent.getChildAt(position);
((Button)viewItem.findViewById(R.id.go)).setVisibility(View.VISIBLE);
((Button)viewItem.findViewById(R.id.re)).setVisibility(View.VISIBLE);
viewItem.invalidate();
clickedItemPos=position;
TextView text = (TextView)viewItem.findViewById(R.id.item);
ime = text.getText();
}
}
hopefully that will fix it. In your stack trace it says line 91 in your class is the line causing the error, what variable is located on that line? that is usually a good indicator of what variable is causing the null pointer, but since we don't know the line numbers for your code it is hard to guess where the issue is.
Yes there is repeated code in that solution but you could always make a method to put the repeated code in and call that instead if you want.
Good Luck, hope this helps.

Related

disabled checkboxes get enabled radomly after recycling view through the adapter in android app

i have the following problem. i have set three checkboxes in my app in a way so when i check one of them the other two get disabled. the problem is that when i scroll up or down namely when the views get recycled some of the disabled checkboxes get enabled which of course i dont want to happen. could you please help me to solve that problem?
the code in the adapter is this :
#NonNull
#Override
public View getView(final int position1, View convertView1, ViewGroup parent1) {
View listItemView1 = convertView1;
if (listItemView1 == null) {
listItemView1 = LayoutInflater.from(getContext()).inflate(R.layout.list_item1, parent1, false);
}
final ColorQuiz currentColorQuiz = getItem(position1);
TextView questionTextView = (TextView) listItemView1.findViewById(question_text_view);
questionTextView.setText(currentColorQuiz.getQuestionHeader());
final CheckBox box1 = (CheckBox) listItemView1.findViewById(R.id.check_Box_view1);
box1.setText(currentColorQuiz.getCheckBoxTextA());
final CheckBox box2 = (CheckBox) listItemView1.findViewById(R.id.check_Box_view2);
box2.setText(currentColorQuiz.getCheckBoxTextB());
final CheckBox box3 = (CheckBox) listItemView1.findViewById(R.id.check_Box_view3);
box3.setText(currentColorQuiz.getCheckBoxTextC());
box1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (box1.isChecked() ) {
thesisA[position1]=true;
box2.setEnabled(false);
box3.setEnabled(false);
} else {
thesisA[position1]=false;
box2.setEnabled(true);
box3.setEnabled(true);
}
int getPositionA = (Integer) compoundButton.getTag(); // Here we get the position that we have set for the checkbox using setTag.
colorQuizs.get(getPositionA).setSelectedA(compoundButton.isChecked());
}
});
box1.setTag(position1);
box1.setChecked(colorQuizs.get(position1).isSelectedA());
.
.
.
and continues the same way with the next two checkboxes (box2, box3).
maybe while you calling box1.setChecked then one of the old listeners is called and it is causing problems (as it still has old tag, and propably setting wrong data to your model ).
Try to add at the beggining to make sure that something wrong does not happen:
box1.setOnCheckedChangeListener(null);
box2.setOnCheckedChangeListener(null);
box3.setOnCheckedChangeListener(null);
This will tell you if not calling callback while property does not change is reason of this problem:
box1.setChecked(!colorQuizs.get(position1).isSelectedA());
box1.setChecked(colorQuizs.get(position1).isSelectedA());

Android EditText setText not updating the text

Hi there. I dont know what is happening. I am trying to change the text of an EditText when creating a DialogFragment, but the EditText is not updating the text.
If I call getText().length() I notice that the content of the EditText changed. But, the visual keeps the same, just empty.
Why?
Thanks in advance people
Here is the code:
public class ItemNameDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(final Bundle bundle) {
System.out.println("ON CREATE DIALOG WAS CALLED"); //This appears on LogCat, so this method is called.. the problem is not that
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Configure an item to count:");
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.itempick_layout, null);
builder.setView(view);
final CheckBox box = (CheckBox) view.findViewById(R.id.itemSenseCheckBox);
final EditText itemNameBox = (EditText) view.findViewById(R.id.itemNameText);
final Spinner spinner = (Spinner) view.findViewById(R.id.itemsDefault);
final int viewIDClicked = getArguments().getInt(clickableViewID);
final String actualName = getArguments().getString(actualNameItemView);
System.out.println("H - before: " + itemNameBox.getText().toString().length()); //it appears on logcat "H - before: 0"
itemNameBox.setText(actualName);
System.out.println("H - after: " + itemNameBox.getText().toString().length()); //it appears on logcat "H - before: 3" so why not changing ?
return builder.create();
}
}
My problem was that below that code, and before the method onCreateDialog ends, I had a few methods controlling a spinner.
The first item of that spinner has the purpose of "select nothing" and in that item choice I was just erasing the content of that edit text, like this:
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
if(pos == 0){
if(editText.length() != 0 )
editText.setText("");
}
And I didnt know that while creating the spinner, it does trigger the event "onItemSelected" and because of that, the edittext was everytime erased, even when I didnt click on that item of the spinner..
So I managed to overcome this by a simple boolean.
Every time the method onCreateDialog I put the boolean to true, and then my onItemSelected just operate when that bolean is false. Like the code below:
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if(firstGoingSpinner){
firstGoingSpinner = false;
}else{
if(pos == 0){
if(editText.length() != 0 )
editText.setText("");
}else{
editText.setText(""+parent.getItemAtPosition(pos));
Editable etext = editText.getText();
Selection.setSelection(etext, editText.length());
}
}
}
I hope this helps someone in the future ;)

Android - Make ImageView Visible When ListItem is selected

I have a listview and each item has a title, some info, and a couple ImageViews I'm using as edit/delete buttons. I don't want to show these "buttons" unless the user selects the row. I can make the "buttons" invisible using:
DeleteButton.setVisibility(View.INVISIBLE);
EditButton.setVisibility(View.INVISIBLE);
in my BindView.
I can make the buttons visible in an onListItemClick:
ImageView DeleteButton = (ImageView) v.findViewById(R.id.button_delete);
ImageView EditButton = (ImageView) v.findViewById(R.id.button_edit);
DeleteButton.setVisibility(View.VISIBLE);
EditButton.setVisibility(View.VISIBLE);
What I can't do is make the "buttons" invisible when selecting another item or scrolling away.
The closest I found was to do a loop through the listitems in the current view and set them all to invisible before making the selected one visible:
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
\\loop through all the items and set them back to invisible
for (int i=0;i<=l.getLastVisiblePosition();i++){
View vChild = l.getChildAt(i);
ImageView DeleteButton = (ImageView) vChild.findViewById(R.id.button_delete);
ImageView EditButton = (ImageView) vChild.findViewById(R.id.button_edit);
DeleteButton.setVisibility(View.INVISIBLE);
EditButton.setVisibility(View.INVISIBLE);
}
\\set the selected one visible
ImageView DeleteButton = (ImageView) v.findViewById(R.id.button_delete);
ImageView EditButton = (ImageView) v.findViewById(R.id.button_edit);
DeleteButton.setVisibility(View.VISIBLE);
EditButton.setVisibility(View.VISIBLE);
}
As you can guess...this approach only works if you have a few items.
I thought about adding a field to the SQLite database my list is using to keep track of the button visibility (similar to what you do for checkboxes) but that seemed silly. Please tell me there's another way.
Another way to do this would be to have an int field in your class that will remember the current position:
private int current = -1;
then in the onItemCLick() method use that field to hide/show your views:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// if it is the first click ignore this part
if (current != -1) {
View last = l.getChildAt(current); // the last one clicked
last.findViewById(R.id.button1).setVisibility(View.GONE); // kill it
}
v.findViewById(R.id.button1).setVisibility(View.VISIBLE);
current = position; // remember the new clicked position
}
If you want the views to be gone also when you scroll the list and those views aren't visible then in the bindView() method add the lines that hide the views:
//...
ImageView DeleteButton = (ImageView) view.findViewById(R.id.button_delete); // view is the view that you get as a parameter
ImageView EditButton = (ImageView) view.findViewById(R.id.button_edit);
DeleteButton.setVisibility(View.INVISIBLE);
EditButton.setVisibility(View.INVISIBLE);
//...
When the use scrolls the list all the views will have the Buttons visibility set to GONE and the onItemCLick() logic will work only for visible views.
I dont know if i understand your question correct but make the definitions of the ImageViews
ImageView DeleteButton = (ImageView) v.findViewById(R.id.button_delete);
ImageView EditButton = (ImageView) v.findViewById(R.id.button_edit);
one time at onCreate() and not every time again! Dont know if this solves your problem but try it.
Edit:
if(tempEditButton != null && tempDeleteButton != null){
tempDeleteButton.setVisibility(View.INVISIBLE);
tempEditButton.setVisibility(View.INVISIBLE);
}
EditButton.setVisibility(View.VISIBLE);
DeleteButton.setVisibility(View.VISIBLE);
tempEditButton = EditButton;
tempDeleteButton = DeleteButton;
This is an old question but I think I can still answer it. I solved this problem by creating a public static method which can be called from anywhere:
public static void hideOptions(Activity activity){
for (int i = 0; i< listviewSize; i++) {
Listview x = (Listview ) activity.findViewById(R.id.contactRecyclerView);
x.getChildAt(i).findViewById(R.id.myView).setVisibility(View.GONE);
}
}
You can then call this method whenever you want to hide your view

Duplicated layout reference in list view

There is an really weird thing happening with my listview. I am creating an ListView with buttons and an editText.
It's disposed like this: [Button] [EditText] [Button], The buttons works like an "incrementer" and "decrementer" updating the numerical value of EditText in 1 unit per click.
The problem is, when I click in an button, almost every time an editText of another list view element is changed (the editText of the clicked item is also changed). And if I click in a button of this erroneous changed item, it also changes the editText of the first one. They basically have the same reference of buttons and editText, although they have textViews with data, and this data is different between they.
To accomplish that I created and custom adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = mInflater.inflate(R.layout.lastproduct_row, null);
holder = new ViewHolder();
holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);
TextView tv;
holder.tvList = new TextView[PRODUCTROW_INT_KEY.length];
for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
tv = (TextView) convertView.findViewById(PRODUCTROW_INT_KEY[i]);
holder.tvList[i] = tv;
}
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
HashMap<String, String> hm = productsList.get(position);
String key = hm.get(CODIGO_KEY);
for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
holder.tvList[i].setText(hm.get(PRODUCTROW_STR_KEY[i]));
}
holder.btnAddQtd.setTag(key+QTD_FLAG+ADD_ACTION);
holder.btnSubQtd.setTag(key+QTD_FLAG+SUB_ACTION);
holder.btnAddQtd.setOnClickListener(handle);
holder.btnSubQtd.setOnClickListener(handle);
if(novosEstoques.containsKey(key)) {
holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
}
return convertView;
}
class ViewHolder {
private TextView []tvList;
private Button btnAddQtd, btnSubQtd;
private Button btnAddQtVol, btnSubQtVol;
private EditText etQuantidade, etQtVolume;
}
I added onClick listenners to the buttons, setting their tags with my listView element ID (concatenated with another informations). Then in my event listener I just get the button parent View (an LinearLayout) and get the EditText from that using getViewAt():
#Override
public void onClick(View v) {
String tag = (String) v.getTag();
if(tag.contains(QTD_FLAG)) {
String []info = ((String) v.getTag()).split(QTD_FLAG);
float qtd;
LinearLayout ll = (LinearLayout) v.getParent();
ll.setBackgroundColor(Color.rgb(0, 128, 30));
EditText et = (EditText) ll.getChildAt(2);
qtd = Float.parseFloat(et.getText().toString().replace(",", "."));
if(info[1].equals(ADD_ACTION)) {
qtd++;
}
else if(info[1].equals(SUB_ACTION)) {
if(qtd > 0)
qtd--;
}
Log.d("TESTE", "MODIFICAR KEY = "+info[0]);
et.setText(qtd+"");
}
}
I'm using an setBackgroundColor in this example to confirm that the LinearLayout instance is duplicated in the lisView. When I click an Button, it's painted in 2 different list view item.
Anyone can point me what could be doing this? I have found people with an duplicated ListView item, I don know if that is my case, cause I have TextView's inside my ListView, and they are not equal, only the LinearLayout portion with buttons and editText is "shared".
I make some changes in my getView method and it's working now! It seems that every time the getView method is called i have not guarantee at all that my editTexts will be filled properly and I didn't realize that. So every getView call I make I set the editText value, if the user edit an ET value, I store it in a HashMap to restore in getView, if there is no entry in HashMap for the given editText, then I set it to the default value (zero):
...
if(convertView == null) {
holder = new ViewHolder();
holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);
//Now it is easier to get etQuantidade reference in button
//click handle, I just have to do:
// public onClick(View v) {
// EditText etButtonAssociated = (EditText) v.getTag();
// ...
// }
holder.btnAddQtd.setTag(holder.etQuantidade);
holder.btnSubQtd.setTag(holder.etQuantidade);
holder.btnAddQtd.setOnClickListener(handle);
holder.btnSubQtd.setOnClickListener(handle);
...
}
else {
...
}
holder.etQuantidade.setTag(key);
if(novosEstoques.containsKey(key)) {
holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
}
else {
holder.etQuantidade.setText("0");
}
return convertView;
Israel,
After looking over your code, I was wondering about an implementation decision you have made. Since each Button is "bound" to a particular EditText, have you considered setting the Tag of those Buttons to the EditText? The Tag may be any Object including a UI element. This is especially useful for dynamic UI elements, such as a runtime populated list.
Since this is handled in your Adapter you wouldn't have to worry about duplicate Parents and such. Additionally, you could avoid having to worry about "finding" the control in your onClick() because you would have it (It's the tag). I'm not sure exactly what your project needs are, but this seems like a potentially viable solution, unless you need those Buttons to accomplish other tasks.
Note of Caution
Just make sure that you erase the Tags' references to the EditText when you are done. Otherwise, you run the risk of leaking some memory.
FuzzicalLogic

get index and id of selected edittext for further processing

New to android and programming in general, so learning concepts as I go.
I have a LinearLayout to which I am adding edittexts dynamically.
I need to be able to get the Index AND Id of any edittext when it is selected or in focus.
I have tried looping through a child count to check for selected like so:
int count = llmain.getChildCount();
for (int i=0; i< count; ++i) {
if ((llmain.getChildAt(i).isSelected()) == true){
//Do Stuff
}
but I have no idea if its even close, and that would be only for index.....
Help would be greatly appreciated!
Thanks
EDIT: still dont have a reliable way to achieve this. The example below with the
if(v instanceOf EditText) {
id = v.getId();
index = ll.indexOfChild(v);
returns a -1 for index and a ten digit number for the id, however, i am assigning an id on creation. ?The odd thing is that the code inside the "if" is running, so it at least thinks it has the focused view. Now, if I change the "instanceof" to a null check like
if (v != null){
id = v.getId();
index = llmain.indexOfChild(v);
AND I add a setFocusableInTouchMode(true), I get a proper return, however, it then acts like i called clearFocus(), because none of the EditTexts are focused. Here is my full proof of concept code that returns the correct values but no longer lets the EditTexts actually have focus.
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&(event.getKeyCode() == 66)) // KeyEvent.* lists all the key codes u pressed
{
View myView = linflater.inflate(R.layout.action, null);
myView.setId(pos);
pos++;
myView.setFocusableInTouchMode(true);
llmain.addView(myView);
myView.requestFocus();
View v = llmain.findFocus();
if (v != null){
id = v.getId();
index = llmain.indexOfChild(v);
Context context = getApplicationContext();
CharSequence text = "index is:" + index + "id is:" + id;
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
return false;
}
This returns the correct values unless I comment the setFocusableInTouchMode line, then it goes back to the odd -1 for index and ten digit for ID. What am I doing wrong? going to have to be a good (and working) answer to get over half of my rep.....
So nobody has a solution for this? its still driving me nuts!
thanks again
My initial thought would be to set the ID equal to the index when adding an EditText, assuming only EditTexts will be in this particular layout:
LinearLayout llMain = (LinearLayout)findViewById(R.id.llmain);
EditText editText = new EditText(this);
//0-based index, so get the number of current views, and use it for the next
editText.setId(llMain.getChildCount());
llMain.addView(editText);
Then, to retrieve the info, put a check into a listener of some sort (onTouch, onFocus, something like that):
#Override
public void onTouch(View v, MotionEvent ev) {
int indexAndId = v.getId();
}
Give this a shot:
LinearLayout ll = (LinearLayout)findViewById(R.id.ll);
int index, id;
//finds the currently focused View within the ViewGroup
View v = ll.findFocus();
if(v instanceOf EditText) {
id = v.getId();
index = ll.indexOfChild(v);
}
That seems like it would work to me, have you tested it and it isn't working?
llmain.getChildAt(i).getId(); will return the views ID to you.

Categories

Resources