Hello I have 3 Type of textViews in my Layout with same Dynamic text but there is only one Difference between them i.e. . Postion . I wanted to show and hide them according to Button Click . but the problem problem occurs when I have to write the same code for five Different TextViews with only one TEXT . Kindly Suggest me Efficient way which could reduce the number of line in my JAVA code.
temperature.setText(temp);
txt.setText(Name);
descptxt.setText(descp);
temperature3.setText(temp);
txt3.setText(Name);
descptxt3.setText(descp);
temperature4.setText(temp);
txt4.setText(Name);
descptxt4.setText(descp);
the number of TextViews will be increase in Future . I am worried about writing same Boiler Plate Code again and Agian
create a function like this:
void setText(String name,String temp,String descp){
for(int i=0;i<txt.size();i++){
temperature.get(i).setText(temp);
txt.get(i).setText(Name);
descptxt.get(i).setText(descp);
}
}
Also instead of creating different variables for each textview create an array of it.
ArrayList<TextView> temperature=new ArrayList<TextView>();
temperature.add((TextView)findViewById(<id>));
//Same for rest of them
And when you want to change text:
setText("","","");
Store each objects in a array ie. temperature objects in a separate array. txt objects in a separate array and descp objects in a separate array.
create a method like
public void setTexts(String temp,String name,String desc){
for(TextView temperature : temperatureArray){
//Change for loop declaration according to your code
//set text for temperature
temperature.setText(temp);
}
for(TextView txt : txtArray){
//Change for loop declaration according to your code
//set text for txt
txt.setText(name);
}
for(TextView descp : descpArray){
//Change for loop declaration according to your code
//set text for descp
descp.setText(desc);
}
}
If your TextViews are logically grouped together, you might want to create one compound View containing all of them:
public class TemperatureView extends ViewGroup { //or whichever layout you use
private TextView textView1;
private TextView textView2;
private TextView textView3;
public void setData(TemperatureData data) {
textView1.setText(...);
textView2.setText(...);
textView3.setText(...);
}
}
In my opinion, this is the most elegant solution in such situation.
You can use alternative in which u can apply loop over childcount of parent layout instead of finding using findViewById.and then using instance of operator ,you can find textviews on which u want to perform the task.
Related
I'm new to Android and JAVA,... my Activity have many widgets that are inside separated LinearLayouts. I want to toggle them on and off accordingly. I have some radio buttons which will hide or show certain LinearLayouts as required. It makes more sense to me having the widgets grouped as sections for this case.
I'm having a problem accessing the methods "getVisibility" and "setVisibility" from inside a "for" loop. I'm using an array of Object type. I thought in maybe just pass the layouts id's as strings but something tells me it will not work.
As a side question : I have 13 total Linear Layouts in a single activity is it bad practice? I could not find a better way to horizontal align elements, maybe I took the short route? :p Thanks in advance.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_job);
...
LinearLayout monthlyContainer = (LinearLayout) findViewById(R.id.monthlyContainer);
LinearLayout weeklyContainer = (LinearLayout) findViewById(R.id.weeklyContainer);
LinearLayout fortnightlyContainer = (LinearLayout) findViewById(R.id.fortnightlyContainer);
LinearLayout fourweeklyContainer = (LinearLayout) findViewById(R.id.fourweeklyContainer);
LinearLayout twiceMonthlyContainer = (LinearLayout) findViewById(R.id.twiceMonthlyContainer);
RadioGroup earningsContainer = (RadioGroup) findViewById(R.id.earningsContainer);
///create a list of views to hide
Object[] viewsToToggle={monthlyContainer, weeklyContainer, fortnightlyContainer, fourweeklyContainer, twiceMonthlyContainer, earningsContainer};
//pass object array to hideView method
this.hideView(viewsToToggle, monthlyContainer);
....
}
private void hideView(Object[] viewsToToggle, Object excludeMe){
///// create array to contain elements to toggle visibility
Object[] viewstoHide = new Object[4];
for(int i = 0; i < viewsToToggle.length; i++){
if(viewsToToggle[i] != excludeMe){
viewstoHide[i] = viewsToToggle[i];
}
}
for(int j = 0; j < viewstoHide.length; j++ ){
if(viewstoHide[j].getVisibility() == View.VISIBLE){ //// syntax error on this line
viewstoHide[j].setVisibility(View.GONE); //// syntax error on this line
}
}
System.out.println("VIEWS TO HIDE : " + Arrays.toString(viewstoHide));
}
Your viewstoHide array does not contain ui elements, so you cannot use those methods. In order to use those methods, change the type of your array or add ui elements like LinearLayout or Radiogroup.
It's not a very good practice to add different types of ojects in your array because when you loop through the array of objects and you if want a to use a specific method on all elements, you can have only one different element and your loop will break. So in order to solve your problem, please use specific type for each array or add only ui elements. Good preactice is to verify if your elements are instanceof desired classes. Hope it helps.
Try making viewsToToggle an Array of LinearLayout instead of an Array of Object.
Same goes for viewsToHide.
My goal is to programmatically change the text size of a Textview item within certain Cardviews, which are contained in a recyclerview. I am successfully able to do that, with an unusual side effect. What happens then is that, although the correct cardviews' textview's properties have been successfully modified, random cards, which are not suppose to be modified, are now modified. However, as the user scrolls through more and more of the recyclerview, both directions, the more and more cards are modified. Eventually, what began with a few random cards (in addition to my request cards) lead to all the calls being modified.
A better example: Let's say I have 5 cards I want to change the text size to something else, within a recyclerview containing 50 cards. Now, those cards, along with a few other, random cards, are now have big text. The rest remain small. As the user scrolls up and down, more and more cards are being set to have big text, until all cards have big text.
How my code works is that I have a class, ListAdapter which extends RecyclerView.Adapter<ListAdapter.VersionViewHolder>. Since I gather my objects from a database, I use arraylists to gather my info, and programmically add them in, as shown:
#Override
public void onBindViewHolder(VersionViewHolder versionViewHolder, int i) {
if (ActivitiesList.size() != 0)
versionViewHolder.title.setText(ActivitiesList.get(i));
if (ActivitiesSubList.size() != 0)
versionViewHolder.subTitle.setText(ActivitiesSubList.get(i));
if (ActivitiesSubList2.size() != 0)
versionViewHolder.subTitle2.setText(ActivitiesSubList2.get(i));
if (ActivitiesID.size() != 0)
versionViewHolder.id.setText(ActivitiesID.get(i));
// TODO: POST QUESTION ON STACK OVERFLOW
if (!ActivitiesTag.get(i).equals("")) {
Log.d("CardPos", Integer.toString(versionViewHolder.getAdapterPosition()));
versionViewHolder.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 56);
}
}
I set ActivitiesList,ActivitiesSubList,ActivitiesSubList2,ActivitiesID, and ActivitiesTag within a child class GradesListAdapter which extends the ListAdapter.
What should be noted is the ActivitiesTag Arraylist. When I wish to add an value to be large, I simply insert any non-empty value into the arraylist. Otherwise, I add an empty string. Thus, for it to be large, it must successfully fulfill the criteria. (On a side note, is there any way of improving this method?) On testing, it appears that only the cards with the correct position are set to be large, but nevertheless it also affects non-tagged cards.
Here is the VersionViewHolder class:
class VersionViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
CardView cardItemLayout;
TextView title;
TextView subTitle;
TextView subTitle2;
TextView id;
public VersionViewHolder(View itemView) {
super(itemView);
cardItemLayout = (CardView) itemView.findViewById(R.id.grades_item);
title = (TextView) itemView.findViewById(R.id.listitem_name);
subTitle = (TextView) itemView.findViewById(R.id.listitem_subname);
subTitle2 = (TextView) itemView.findViewById(R.id.listitem_subname2);
id = (TextView) itemView.findViewById(R.id.listitem_id);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
clickListener.onItemClick(v, getAdapterPosition());
}
}
What can I do to remove this unintended side effect? I believe I have all the data needed for others to help debug this, but if I'm missing something, please say so; I'm still quite new to StackOverflow.
Thank you for reading.
In your onbindViewHolder, change
if (!ActivitiesTag.get(i).equals("")) {
Log.d("CardPos", Integer.toString(versionViewHolder.getAdapterPosition()));
versionViewHolder.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 56);
}
to
if (!ActivitiesTag.get(i).equals("")) {
Log.d("CardPos", Integer.toString(versionViewHolder.getAdapterPosition()));
versionViewHolder.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 56);
}else{
versionViewHolder.title.setTextSize(TypedValue.COMPLEX_UNIT_SP,"Your Original Text Size");
}
If you only set an if clause without an else clause in viewholder, since this view is reused again and again, your text size will not be reset to normal. So, you'll have to manually reset the text size.
For example I have Hello123456 string and I want to show it as just Hello in a TextView.
I need those numbers in my code and I can't erase them.
EDIT:
All answer are providing a way that I erase the numbers and then set it to textview, But I want them to be there.
I get the "hello" part from user and I add the number part to it and this will be the name of a listview Item. but I want to show just the hello part in listview and also if I checked if that listview clicked item ends with "123456" it returns true.
I want to show it as just "Hello" in a TextView.
Then just put Hello in your TextView without cutting your string or create an temporary string to hold the "Hello" String.
If your string is like this "HELLOHI12345" then you need a regex to eliminate all the number string within it.
sample:
textview.setText(s.replaceAll("[0-9]+", ""));
Also take note that string are immutable so the original String wont get replaced after executing replaceAll
Use this dude ! :) You can use contextDescription to access the actual text
textView.setText(yourText.replaceAll("[0-9]",""));
textView.setContentDescription(yourText);
textView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String str = ((TextView) v.getContentDescription()).toString();
}
});
A TextView can have a tag attached to it i.e. some object that is stored as extra data to the view itself. Check out the documentation here:
View.setTag(Object)
In your case, you can assign the "Hello" to the displayed text (using the method below), and set the tag to the full text.
textView.setText(getDisplayText(helloString));
textView.setTag("TAG", helloString);
When the user clicks on your view, you can get the tag from the view and do what you need with it.
This way, there is more data stored than what you see.
(original answer before the edit)
How about a method that does what you need:
private String getDisplayText(String input)
{
return input.substring(0, 5);
}
And then just use that method when you set the value of your TextView.
textView.setText(getDisplayText(helloString));
use \\w+ regex with Pattern and Matcher classes. This will also work if you don't know the String length. The String can be hello123 or olo123
Its not possible to hide the characters in a string. You have to solve your problem in a different way. My suggestion is to implement a separate class which contains the string:
I would write an class which contains the string. Then add two methods to this class which returns the string for display and for internal use. E.g.
class DataObject {
private String data;
public String forTextView() {
//code from one of the answers above, may be the regex version
}
public Stringg getStringWithNumbers() {
return data;
}
}
This allows you to show the string without the numbers and still have them ready when you use them.
//first i have this method , below is my question
public void addrows(){
TableRow fila;
tabla = (TableLayout)findViewById(R.id.tabla);
TextView txtNombre;
for(int i = 0;i<id;i++){
String x[] = helper.leer();
layoutFila = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT);
caja= new CheckBox(this);
fila = new TableRow(this);
fila.setLayoutParams(layoutFila);
txtNombre = new TextView(this);
txtNombre.setId(i);
txtNombre.setTextSize(17);
txtNombre.setText(x[i]);
txtNombre.setGravity(Gravity.LEFT);
// txtNombre.setLayoutParams(layoutTexto);
caja.setText("");
caja.setId(i);
fila.addView(txtNombre);
fila.addView(caja);
tabla.addView(fila);
}
}
i know that when the oncreate() method start the checkboxes objects are created and then i assign an numerical id from 0 to wherever the for cycle stop , but later in the program i need to retrieve what checkboxes were clicked so first i need the id but eclipse wont let me put the numerical id, please help! and sorry for my English i'm a noob in android and the English language
this.CheckBox = (CheckBox)this.findViewById(R.id.?);
As You may read in View class documentation ID should be unique within a tree You search.
You set same id for TextView and Checkbox.
If You know You are going to access them all later after creation keep references to them in array instead of trying to retrieve them later using findViewById.
But even better solution would be to set onClick event listener for them and keep track of checking/unchecking them.
In #HalR's answer You may read how to set onCheckedChanged event listeners for Your checkboxes. Folowing his solution will have an ArrayList of checked checkboxes.
Next step, You have to increment values of correct TextView so You need to couple CheckBoxes and TextViews.
I think best for this would be to set Tag for CheckBox with value of TextView id.
So after user submits You iterate over List of checkboxes, getTag and use it in findViewById to get TextView and update its value.
Id (short for IDentifier) is an integer to uniquely identify elements, You can use it in findViewById to get view elements. You can read more about ID in this answer
Tag is used to associate View element with some extra data as You may read in getTag documentation. It takes as parameter Object type so You set as tag anything not only numbers. In Your case You could set as ChechBox's tag a TextView instead of its id and it will work too.
You are manually setting your id to the index of the row, which is something I don't think I'd do. I'd normally use setTag() to identify my object.
I think it would be easier to use a listener to detect when the checkboxes have been checked, and you can track the changes when the check happens.
use something like this:
In your Activity, create a ArrayList
ArrayList<CheckBox> checkedBoxes = new ArrayList<CheckBox>();
then in your creation:
caja= new CheckBox(this);
caja.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
int index = buttonView.getId();//pulling back the number you set originally, if that is what you like. I would get the tag I had set, and maybe do something here.
//do something in here!
if (buttonView.isChecked()) {
//including this checkbox in the list of checked boxes
checkedBoxes.addObject(buttonView);
} else {
//take it out of the list of checked boxes
checkedBoxes.removeObject(buttonView);
}
}
};
Some info on Id vs Tag
Id is a numeric value that identifies the view in the view hierarchy. If you are using things in your layout, like aligning one view with another, they look for and expect a view with a specific id. So in layout, you'll have android:id="#+id/bigBox" and that will create some number that it associates with bigBox. When you find that view, with findViewById() that is the number it is looking for. When you manually set those numbers, it seems like you are asking for trouble. If you set a view's id to 2, then you should be able to find it with myView = findViewById(2).
Tag is a nicely little object pointer that you can pass along with your view. Quite often it will be a row number:
Integer saveMe = new Integer(i);
checkBox.setTag(saveMe);
Or it can even be a pointer to your original data object that you used to create that row. If you had created each row using a contact, you could use
myRow.setTag(contact)
and later when you clicked on that row, you would just use
contact = (Contact)myRow.getTag()
and you would have your original contact back. Its way cleaner than keeping big arrays of your rows or checkboxes, or whatevers. Just use listeners that detect when you do something, that is a much better way.
Oh, and if you if you do have an onClick(View view) that is triggered by your CheckBox, that view IS your CheckBox.
CheckBox theBoxIJustChecked = (CheckBox)view;
You don't need to look it up with some id. It's right there.
If you want to go this way than you should just do the apposite operation i.e.:
for(int i = 0; i < n; ++i){
...
...(CheckBox))this.findViewById(i);
...
}
It should work for you
However be careful as if you have number of views with the same id inside the view-tree than findViewById(i) can return an unexpected result such as returning the first view in view-tree with given id (it can be not of CheckBox type which can lead to ClassCAstException)
Update in reply to comment
If you want to make some sort of logical connection CheckBox-TextView there are several options:
You can make a sort of function like the following (assuming that there is the limit of CheckBoxes and TextViews quantity):
Code:
private static int CHECK_BOX_MAX_NUMBER = 10000;
public void int getTextVieIdByCheckBoxId(int checkBoxId){
if(checkBoxId >= CHECK_BOX_MAX_NUMBER){
// you can throw an exception here for example
}
return CHECK_BOX_MAX_NUMBER + checkBoxId;
}
And then you should set id's to your TextViews with that function.
checkBox.setId(i);
textView.setId(getTextVieIdByCheckBoxId(i));
....
// add Views to your layout
....
(CheckBox)this.findViewById(i);
TextView)this.findViewById(getTextVieIdByCheckBoxId(i));
or
2.I think there is a little bit more accurate method:
Just use setTag() of CheckBox instances to set appropreate TextView inside in order to create interconnection. In thiscase you have to store all the created checkBoxes in some List or array:
List<CheckBox> checkBoxList = new ArrayList<CheckBox>();
for(int i = 0; i < n; ++i){
...
CheckBox checkBox = new CheckBox();
TextView textView = new TextView();
checkBox.setTag(textView);
checkBoxList.add(checkBox);
}
Then you can achieve what you want like this:
int textBoxListSize = checkBoxList.size();
for(int i = 0; i < textBoxListSize; ++i){
CheckBox checkBox = checkBoxList.get(i);
if(chechkBox.isChecked()){
TextView textView = (TextView)checkBox.getTag();
//do whatever with textView
}
}
Here you don't need to generate id's and worry about collisions which could accure
I have some part of an android app here which crashes for no apparent reason.
RL0 happens to be some LinearLayout defined in XML which already contains some other irrelevant stuff. To be honest with you, I've mostly worked with C++ so I might not initially know much about why some things are done significantly different in android, but I'm putting effort. Any help on how I can fix that crash?
Error message states NullPointerException.
Thanks.
public class Osteoporoza extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_osteoporoza);
LinearLayout RL0=(LinearLayout)findViewById(R.id.RL0);
page[] pages=new page[10];
RL0.addView(pages[0].pageLL0);//doesn't crash without this line, yet i need to have some way of adding n objects that follow a pattern, i.e. a class.
class page
{
public LinearLayout pageLL0;
public ScrollView pageUpperScroll1;
public TextView pageTextView2;
public ScrollView pageLowerScroll1;
public LinearLayout pageAnswerButtonLL2;
public Button AnswerButton3_1;
public Button AnswerButton3_2;
public Button AnswerButton3_3;
public Button AnswerButton3_4;
page()
{
pageAnswerButtonLL2.addView(AnswerButton3_1);
pageAnswerButtonLL2.addView(AnswerButton3_2);
pageAnswerButtonLL2.addView(AnswerButton3_3);
pageAnswerButtonLL2.addView(AnswerButton3_4);
pageLowerScroll1.addView(pageAnswerButtonLL2);
pageUpperScroll1.addView(pageTextView2);
pageLL0.addView(pageUpperScroll1);
pageLL0.addView(pageLowerScroll1);
}
}
All elements in an Object array are null by default.
I.e. when you create the array:
page[] pages = new page[10];
you are only setting the size of the array but not setting any instances within the array itself so every element will be null. To instantiate each element you need to use:
for (int i=0; i < pages.length; i++) {
pages[i] = new page();
}
Note Java naming conventions show that class names start with an uppercase letter, for example
Page[] pages = new Page[10];
- You have declared the Array but didn't initialize it.
Eg:
page[] pages = new page[10]; // Tell that this is an Array of page of length 10
- You will need to Initialize it,
Eg:
for (page p : pages){
p = new page();
}
- Please use the Collection like ArrayList instead of Array, as its far more flexible than using an Array.
- ArrayList can hold null values, and unlike Array, its size can increased.
ArrayList<page> p = new ArrayList<page>();
- Always make the 1st letter of a class, enum , interface as Capital.
Eg:
It should Not page but Page