I am getting to change the visibility of one of the buttons on my viewpager but I am getting a Null Pointer Exception on this line:
save_button.setVisibility(Button.INVISIBLE);
I am wondering why that is? Is it because I am not getting the visibility property inside of my InstantiateItem() for the button? Should I? If so, how do I change the button visibility based on the fact if the page is viewed by the user or not?
What I am trying to do is: Show the save button if all the views are viewed in the viewpager. If not all the views are viewed, then hide the save button.
Here is my code:
boolean isViewed = false;
boolean buttonState= false; //unpressed, if true == pressed
int buttonValue = 0;
//Methods
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score_viewpager);
//Specify the number of pages/views
numberOfPages = new Integer[]{1, 2, 3, 4, 5};
final Button save_button = (Button) findViewById(R.id.save);
//Initialize adapter to populate view
myAdapter = new MyAdapter(ScoreCollectionPager.this, numberOfPages, save_button);
//Search view for viewpager Id and set the adapter on the first item
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(myAdapter);
viewPager.setCurrentItem(0);
//Attach the page change listener inside the activity
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
Button save_button = (Button) findViewById(R.id.save);
// This method will be invoked when the current page is scrolled
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//This method will be invoked when a new page becomes selected
#Override
public void onPageSelected(int position) {
//get position
isViewed = true;
if (isViewed && (position == numberOfPages.length)) {
save_button.setVisibility(Button.VISIBLE);
}
else {
save_button.setVisibility(Button.INVISIBLE); // Null Pointer Exception here? why?
}
}
// Called when the scroll state changes:
// SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
#Override
public void onPageScrollStateChanged(int i) {
//get state
}
});
}
private class MyAdapter extends PagerAdapter {
//fields
Button save_button;
//Constructor
public MyAdapter(Context context, numberOfPages, Button save_button) {
this.context = context;
this.numberOfPages = new ArrayList<Integer>(Arrays.asList(numberOfPages));
this.save_button = save_button;
}
//Returns total number of pages
#Override
public int getCount() {
return numberOfPages.size();
}
/**
* Create the page for the given position.
*
* #param parent The containing View in which the page will be shown.
* #param position The page position to be instantiated.
*
* #return Returns an Object representing the new page. This does not need
* to be a View, but can be some other container of the page.
*/
#Override
public Object instantiateItem(ViewGroup parent, final int position) {
//Get the inflater
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//inflate the root layout
View view = inflater.inflate(R.layout.score_collection, null);
//Save Button
save_button = (Button) view.findViewById(R.id.save);
save_button.setOnClickListener(new ViewGroup.OnClickListener() {
public void onClick(View view) {
//code for saving
}});
}
}
Move the below piece of code inside onPageSelected mehtod
Button save_button = (Button) findViewById(R.id.save);
I can see that Button instances are not the same. Make sure that you get the same object in the same layout. The first 2 buttons in your code belong to layout R.layout.score_viewpager, the last one belongs to R.layout.score_collection (in MyAdapter).
OK. It's a mess, but if you in onCreate give value to a class variable, you can access it in the other internal classes without having to call findViewById several times (expensive call).
Class var:
private final Button saveButton;
Set value in onCreate:
saveButton = (Button) findViewById(R.id.save);
Related
I have an android fragment, that has a listview. for that listview I implemented an inner OnItemClickListener class.
When there's a click, I save the selection in a global variable called SelectedIndex.
If I click again on that list, I can see the previous selection correctly, So its saving the state on the global variable correctly.
The problem is when I try to access to that same global variable from another inner class, for example, one class used for listen to clicks on a button. Is always showing the value I used for initialize the varialbe (-1).
The code of the fragment:
/**
* A placeholder fragment containing the view for the recentCalls list
*/
public class RecentCallsFragment extends Fragment {
private Cursor cursorAllRows;
private RecentCallsTable rcTable;
private ListView list;
private RecentCallsAdapter adapter;
Button btnDelete, btnCreditRequest, btnCreditBlock, btnSendTo;
int selectedIndex; //this is the global variable that I am using.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rcTable = new RecentCallsTable(getActivity());
cursorAllRows = rcTable.getRecentCallsCursor();
adapter = new RecentCallsAdapter(getActivity(), cursorAllRows);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
list = (ListView) view.findViewById(R.id.listViewMain);
btnDelete = (Button) getActivity().findViewById(R.id.buttonDelete);
btnCreditRequest = (Button) getActivity().findViewById(R.id.buttonCr);
btnCreditBlock = (Button) getActivity().findViewById(R.id.buttonCRD);
list.setAdapter(adapter);
list.setOnItemClickListener(new ItemClickHandler()); //Add the inner ItemClickLister
btnSendTo = (Button) getActivity().findViewById(R.id.buttonSendTo);
btnSendTo.setOnClickListener(new DebugOnClick());//here I add the inner clicklister
return view;
}
/**
* Class that handles the one click action on the list
*/
public class ItemClickHandler implements AdapterView.OnItemClickListener{
//when there's one fast click, keep the selection on the item or remove it if already has it
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
int prevSelection = adapter.getSelectedIndex();
Toast.makeText(getActivity(), Integer.toString(selectedIndex), Toast.LENGTH_SHORT).show();
int newSelection = position;
if(prevSelection == position){
newSelection = -1;
}
selectedIndex = newSelection; //here I change the value of the global variable
adapter.setSelectedIndex(newSelection);
adapter.notifyDataSetChanged();
}
}
public class DebugOnClick implements View.OnClickListener{
public DebugOnClick(){
}
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), Integer.toString(selectedIndex), Toast.LENGTH_SHORT).show(); //here I show the value of the global variable and is always -1
}
}
}
Which may be the problem?
There is one possibility that comes into my mind. When you have an inner class instantiated it implicitly binds with an instance of the hosting class (as if it were a reference of the hosting class). So I assume that the inner classes that you use are each linked with a different instance of the hosted class and thus using a different selectedIndex. Your global variable is not really global, its an instance variable.
I just found the problem. The buttons are in the main activity, so I just moved the global variable to the main Activity and started to manipulate it from the fragments like this:
MainActivity ma = (MainActivity) getActivity();
ma.rcSelected = newSelection;
the title is a bit confusing sorry about that i didnt know how to put it in words properly. I have a listView that uses an Adapter that i created myself. When the first row of the listView is pressed I have made it so it creates a new object from class called Ship that has 3 integer values. Below
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hangar);
ListAdapter adapter = new HangarAdapter(this, ship);
hangarList.setAdapter(adapter);
hangarList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Intent sendListEvents = new Intent();
if(position == 0)
{
Ship ship1 = new Ship();
ship1.setAddAmount(50);
ship1.setAddTime(5000);
ship1.setAddSpend(1000);
ship1.shipAdd();
}
}
}
In my adapter i have a textView called TextView2 and I want to set the text of it to ship1's value called addSpend. How do i do that.
if (position == 0) {
theImageView.setImageResource(R.drawable.planet);
TextView2.setText("This is where I want ship1's addSpend value to be displayed")
}
Well if I am correct then you have in the HangarAdapter class the object this (which references to the Activity in which you are right now: ListAdapter adapter = new HangarAdapter(this, ship);). Save this object to an variable (I call it MainActivity) in the HangarAdapter class .
Now you could just say in the HangarAdapter class: MainActivity.findViewById("TextBoxID").setText("MUHAHAHAH")
I currently have a scrollview which I am adding rows to by inflating another xml layout. This is all working as it should and the row are all appearing correctly.
The issue I am having is that I am not sure how I can detect which button has been selected.
I have shown some example code for 1 on by buttons, simply put when this button is selected it toggles between 2 images. However, whenever I press the button it always automatially toggles the bottom rows button rather than the row in which the button has been selected.
Is there a way this can be implemented whilst still inflating a view to be used as a row (I do not want to dynamially create the rows, as this gets very messy)?
ScrollView scrollWeapons = (ScrollView)findViewById(R.id.scrollWeapons);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
int i = 0;
for(final Weapon w : Game.Weapons)
{
View view = new View(this);
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.menuweapons_row, null);
btnSelected = (ImageButton)view.findViewById(R.id.btnSelected);
btnSelected.setId(i);
btnSelected.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
EquipUnequip(w.WeaponID());
}
});
}
private void EquipUnequip(int WeaponId)
{
if(Game.Weapons.get(WeaponId).CharacterID() == ChrSelected)
{
btnSelected.setImageResource(R.drawable.eqip_but_idle);
}
else
{
btnSelected.setImageResource(R.drawable.eqip_but_press);
}
}
ll.addView(view);
i++;
The onClick method of OnClickListener has a parameter v. The value of v will be the View that was clicked, i.e. the ImageButton. All you have to do now is pass the View to EquipUnequip:
...
btnSelected.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
EquipUnequip(w.WeaponID(), (ImageButton)v);
}
});
...
private void EquipUnequip(int WeaponId, ImageButton btnSelected) {
if(Game.Weapons.get(WeaponId).CharacterID() == ChrSelected) {
btnSelected.setImageResource(R.drawable.eqip_but_idle);
} else {
btnSelected.setImageResource(R.drawable.eqip_but_press);
}
}
PS: This part seems a bit non-sensical to me:
View view = new View(this);
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.menuweapons_row, null);
Why do you create a new View just to do nothing with it and replace it with the result from the LayoutInflater?
Edit
If you really need the row of the View (and it never changes) here are 2 alternatives:
Save row in the OnClickListener
class MyOnClickListener implements OnClickListener {
private final int rowIndex;
MyOnClickListener(int rowIndex) {
this.rowIndex = rowIndex;
}
#Override
public void onClick(View v) {
// do something with rowIndex
}
}
and use it instead of your anonymus class
or simply add a final variable outside your anonymus class:
// currentRowIndex calculated by your program
// i.e. incremented in every iteration
final int rowIndex = currentRowIndex;
btnSelected.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// do something with rowIndex
}
});
Add the info as tag to the button (currentRowIndex would be of type int):
btnSelected.setTag(currentRowIndex); // attach Integer data to the view
btnSelected.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int rowIndex = (Integer)v.getTag();
// do something with rowIndex
}
});
Give the View parameter of onClick() to EquipUnequip(), cast this to ImageButton and use it. Otherwise you get the last created button.
I'm having troubles saving the state of a selected radiobutton when the user hits the back key and then comes back to the activity. My class extends ListActivity. Here's the onCreate and onBackPressed() methods of the class that creates the listview.
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.profile_manager);
dataInfo = new HandleData(ProfileMaker.this);
dataInfo.open();
people = dataInfo.getAllComments();
userAdapter = new ArrayAdapter<People>(ProfileMaker.this, android.R.layout.simple_list_item_single_choice, people);
setListAdapter(userAdapter);
registerForContextMenu(getListView());
addUser = (Button) findViewById(R.id.buttonAddUser);
graphUser = (Button) findViewById(R.id.buttonGraph);
addUser.setOnClickListener(this);
graphUser.setOnClickListener(this);
idSharing = getSharedPreferences(idPref, 0);
nameSharing = getSharedPreferences(namePref, 0);
ageSharing = getSharedPreferences(agePref, 0);
weightSharing = getSharedPreferences(weightPref, 0);
genderSharing = getSharedPreferences(genderPref, 0);
otherName = getSharedPreferences(nameThere, 0);
otherAge = getSharedPreferences(ageThere, 0);
otherWeight = getSharedPreferences(weightThere, 0);
otherGender = getSharedPreferences(genderThere, 0);
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
Intent newIntent = new Intent(ProfileMaker.this, Monitor.class);
startActivity(newIntent);
}
Whenever I press the home button and come back to the application, the radiobutton that I selected is still selected, but when I press the back key to go to the previous activity and then come back to this one, the radiobutton is not selected. How can I save the state of a previously selected radiobutton? These radiobuttons are in a radiogroup. Any help is highly appreciated. Thanks.
EDIT:
Ok, so this is what I got.
public class AdapterClass extends ArrayAdapter<People>{
private final List<People> list;
private final Activity context;
public AdapterClass(Activity context, List<People> list) {
super(context, R.layout.profile_manager, list);
this.context = context;
this.list = list;
}
static class ViewHolder {
protected TextView text;
protected RadioButton radioButton;
RadioGroup group;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.button_layout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.radioButton = (RadioButton) view.findViewById(R.id.check);
viewHolder.radioButton
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
People element = (People) viewHolder.radioButton
.getTag();
element.setSelected(buttonView.isChecked());
}
});
view.setTag(viewHolder);
viewHolder.radioButton.setTag(list.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).radioButton.setTag(list.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.radioButton.setChecked(list.get(position).isSelected());
return view;
}
I got excited when it actually had a radiobutton selected. But the problem is it only selects the first button in the list an nothing else even if I deselected it and selected another item. Also, it's letting me select more than one radio button which I don't want. What am I missing?
You are losing the state of the radiogroup as you are navigating using intent when the back key is pressed, so activity reinitializing (i.e Again when you come to your screen it will start from oncreate) , you need to add extras to your intent send you radio button states
example like this
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
Intent newIntent = new Intent(ProfileMaker.this, Monitor.class);
newIntent.putExtra("somename",state of the radiobutton);
startActivity(newIntent);
}
and in ProfileMaker activity check is there any extra , if there is an extra get that and select radiobutton according to that.
if (getIntent().getExtras().getString("yourextraname") != null)
applicant = getIntent().getExtras().getString("applicant");
Make an boolean array and fill it with false value as number of radio buttons.Now when ever you click radio button make that index true if it was false and if clicked again do it false. Use your own list adapter it will helps you more . I had done similar in case of check box you can see my post Unable to check/uncheck CheckedTextView inside getView . Reply me if this helps you ...
I have a Button Adapter, i make 9 buttons in a gridview, then i set id for each button. BUt how do i use a button in another class, example: i need to change background of button with id 5. Here's my code
public class ButtonAdapter extends BaseAdapter {
static Button btn;
private Context mContext;
// Gets the context so it can be used later
public ButtonAdapter(Context c) {
mContext = c;
}
// Total number of things contained within the adapter
public int getCount() {
return somestringarray.length;
}
// Require for structure, not really used in my code.
public Object getItem(int position) {
return null;
}
// Require for structure, not really used in my code. Can
// be used to get the id of an item in the adapter for
// manual control.
public long getItemId(int position) {
return position;
}
public View getView(int position,
View convertView, ViewGroup parent) {
if (convertView == null) {
// if it's not recycled, initialize some attributes
btn = new Button(mContext);
btn.setLayoutParams(new GridView.LayoutParams(85, 85));
btn.setPadding(8, 8, 8, 8);
btn.setOnClickListener(new MyOnClickListener(position));
}
else {
btn = (Button) convertView;
}
btn.setText(somestringarray[position]);
// filenames is an array of strings
btn.setTextColor(Color.BLACK);
btn.setBackgroundResource(INTarraywithpictures[position]);
btn.setId(position); //here i set Id
return btn;
}
}
After calling setContentView, you can use Button b = (Button)findViewById(theButtonId); to get a reference to it.
you can use setTag(value) and getTag(value) instead of setId()...
for more info..go setTag and getTag
if u want to access your button in another class just declare the button as final and static....and if u declare the button as public then u can access the button in another class by creating the object of the class which contains button.