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.
Related
I am doing a project and this partly has a function of a search engine that highlights the words that are searched.
I have an EditText and a button that when pressing the button highlights the word in the EditText.
It works perfectly if you search for it in a single TextView as I assign the findViewById(R.id.textView1) to it
but how do I do if I have more than 100 TextView? I'm doing a long manual.
In addition, each TextField in the XML has different names.
For example textView1, txView1, textView2, txVi1, etc
Is it possible what I need to do? I looked in many places and couldn't find anything.
I leave you part of the .java code
public class Medicina extends AppCompatActivity {
EditText searchview;
Button btnBuscar;
boolean isHighlight = false;
TextHighlighter textHighlighter;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_medicina);
searchview = (EditText)findViewById(R.id.searchview);
btnBuscar = (Button)findViewById(R.id.btnBuscar);
btnBuscar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
if (!isHighlight){
textHighlighter = new TextHighlighter();
textHighlighter.setBackgroundColor(Color.parseColor("#FFFF00"))
.setBackgroundColor(Color.RED)
.addTarget()
.highlight(searchview.getText().toString(),TextHighlighter.BASE_MATCHER);
}
isHighlight = !isHighlight;
}
});
}
In the .addTarget() would go the findViewById (R.id.lalala)
And it would work if you only had a single TextView, but it's hundreds.
Thank you
The first almost 300 lines of XML code (from here on it's all the same, the vast majority TextView and ImageView).
I upload the code to GitHub because it gives me an error when pasting it in the post.
https://github.com/lautarovculic/activity_medicina
You can assign an id for the ViewGroup that contains all the TextView. Then obtain the ViewGroup by findViewById(R.id.viewgroup) and loop through all ViewGroup's child view to get all of its TextView.
public List<TextView> getAllTextViewsSimple() {
final List<TextView> result = new ArrayList<>();
final ViewGroup viewGroup = findViewById(R.id.viewgroup);
for (int i = 0; i < viewGroup.getChildCount(); i++) {
final View v = viewGroup.getChildAt(i);
if (v instanceof TextView) {
result.add((TextView) v);
}
}
return result;
}
If you want an even more general approach in case the TextView may not be placed in the same ViewGroup. Assign an id to the outmost ViewGroup then obtain and pass it as a parameter to a recursive function to get all child TextView.
public List<TextView> getAllTextViews(View v) {
final List<TextView> result = new ArrayList<>();
if (v instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup) v;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
result.addAll(getAllTextViews(viewGroup.getChildAt(i)));
}
} else if (v instanceof TextView) {
result.add((TextView) v);
}
return result;
}
The code snippet to help you use it with TextHighlighter
final List<TextView> allTextViews = getAllTextViewsSimple();
textHighlighter.setBackgroundColor(Color.parseColor("#FFFF00"))
.setBackgroundColor(Color.RED);
for (TextView tv : allTextViews) {
textHighlighter.addTarget(tv);
}
textHighlighter.highlight(searchview.getText().toString(),TextHighlighter.BASE_MATCHER);
I want to update in and ArrayAdapter a TextView when user will click + or - button. I cannot figure out how can I change data of individual in ArrayApapter.
Here is a image for better explanation what I want to do :
public View getView(int position, View countView, ViewGroup parent) {
View listView = countView;
if (listView == null) {
listView = LayoutInflater.from(getContext()).inflate(R.layout.listview, parent, false);
}
word currentWord = getItem(position);
TextView foodName = (TextView) listView.findViewById(R.id.food);
Button minus = (Button) listView.findViewById(R.id.minus);
Button add = (Button) listView.findViewById(R.id.add);
TextView total = (TextView) listView.findViewById(R.id.total);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
return listView;
}
Whenever you are making a change through onclicklistener then just only change your data. like if your are using ArrayList> then just change the any value whatever you want like if your press 4th element with add+ then get the 4th item from the list and set it to +1. and then refresh your adapter with notifydatasetChanged().
In the above code you are only showing the UI part in the list whenever you will use data with you can do it then very easily.
Inside onClickListener, Increase or decrease the quantity and call onDataSetChanged().
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);
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 this code inside my BaseAdapter Adapter:
public View getView(final int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.facebook_friends_layout, null);
TextView friendsName = (TextView)vi.findViewById(R.id.tvFacebookName); // Friends thumb
friend_image=(ImageView)vi.findViewById(R.id.ivFacebookPicture); // thumb image
song= new HashMap<String, String>();
song = data.get(position);
friendsName.setText(song.get(MyFriends.KEY_FBNAME));
//Log.i("Facebook Pangalan", ""+MyFriends.KEY_FBNAME);
FriendName = (String) friendsName.getText().toString();
FBID = song.get(MyFriends.KEY_FBID);
String fbAvatarUrl = "http://graph.facebook.com/"+ FBID +"/picture";
//Log.i("FBID", FBID);
BitmapManager.INSTANCE.loadBitmap(fbAvatarUrl, friend_image, 100,100);
Button btn=(Button)vi.findViewById(R.id.btnAdd);
if (FBID.equals(""))
{
btn.setVisibility(View.GONE);
}
else
{
btn.setVisibility(View.VISIBLE);
}
btn.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//FACEBOOK FRIENDS
Log.i("", ""+FriendName);
//AddfromFacebookFriends();
}
else if (LOCK_BASEDATA.equals("1"))
{
//MY REQUEST
//((MyFriends)context).SetMyRequest();
//Log.i("LangYa", "Langya");
}
else if (LOCK_BASEDATA.equals("2"))
{
//FRIEND REQUEST
//((MyFriends)context).SetFriendRequest();
//d2papasok
AddFriendRequest();
}
}
});
return vi;
}
I am logging my friend's name whenever I click on the button. Now my problem starts when I click the button; I am not getting my desired string. It is getting the string from another row of my listview.
EDIT
Thanks, actually ive just aaded this code
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//Object x =btn.getTag();
//String sa = x.toString();
View parentView = (View) arg0.getParent();
String textviewtext = ((TextView) parentView.findViewById(R.id.hiddentv)).getText().toString();
//FACEBOOK FRIENDS
AddfromFacebookFriends(textviewtext);
}
else if (LOCK_BASEDATA.equals("1"))
{
I am just getting my parents View to get my desired textview and now it works. Thanks anyway
You are trying to get the FriendName using this code:
TextView friendsName = (TextView)vi.findViewById(R.id.tvFacebookName);
FriendName = (String) friendsName.getText().toString();
This is not The FriendName of the ListView item you clicked. Its the FriendName of the newly created ListView item. Because in getView(), the ListView item you get is the newly created one.
One way to solve this is:
Use tags like KunalK suggested. I am not sure if it works...i never tried it.
Or the other way is:
onButtonClicked get the Position of the ListView item you clicked, and get the respective Name from the ArrayList you are using.
Here the Position is not the position parameter in the getView(). That gives the position of the newly created ListView item again.
Use this to get the actual position of the clicked item:
int clickedItemPosition = yourListView.getPositionForView((View) yourButton.getParent());
you should go with this by setting the "FriendName" in your button's setTag property. and whenever you handle your button click event fetch your FriendName String by using getTag property of button. for e.g. something like this:
....
btn.setTag(FriendName);
btn.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
LOCK_BASEDATA = MyFriends.LOCK_BASEDATA;
if (LOCK_BASEDATA.equals("0"))
{
//FACEBOOK FRIENDS
Log.i("", ""+btn.getTag().toString());
//AddfromFacebookFriends();
}
else if (LOCK_BASEDATA.equals("1"))
{
//MY REQUEST
//((MyFriends)context).SetMyRequest();
//Log.i("LangYa", "Langya");
}
else if (LOCK_BASEDATA.equals("2"))
{
//FRIEND REQUEST
//((MyFriends)context).SetFriendRequest();
//d2papasok
AddFriendRequest();
}
}
});
....
Getting the name from the list can be accompished by using an onListItemClick method as follows (not in your adapter, but in the class with your list):
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
TextView friendsName = (TextView)v.findViewById(R.id.tvFacebookName);
FriendName = (String) friendsName.getText().toString();
}
Since this code is the onListItemClick method, the View v parameter is the view of the row you clicked. Once you have that, you search that particular row view for the TextView you want and then pull the string from that.
You had the right idea, you just put it in the wrong place.