I'm trying to convert a c# windows form program over to android and I'm at the very last piece that I can't seem to figure out the translation for.
I have 9 buttons in a framelayout that I need to remove the text from either by iterating or by grabbing all at once.
In my original program I used a foreach loop like this:
foreach(control boardPosition in gameBoard)
{
((Button) boardPosition).Text ="";
((Button) boardPosition).ForeColor = Color.Black;
}
This is what I've gotten so far
FrameLayout GameBoard = (FrameLayout) findViewById(R.id.GameBoard)
for(Button boardPosition : GameBoard)
{
boardPosition.setText("");
boardPosition.setTextColor(Color.BLACK);
}
The error that I'm receiving is just "foreach not applicable to type 'android.widget.Framelayout' "But I'm not sure whats it's replacement or if it has one.
The object you are looping against must implement iterable interface. Java must know that it can be iterated in some kind. FrameLayout is not iterable. It doesn't know your intentions that you have array of buttons in it.
For looping every button in layout I would use something like this:
FrameLayout layout = (FrameLayout) view.findViewById(R.id.frame);
int children = layout.getChildCount();
for (int i = 0; i < children; i++) {
View view = layout.getChildAt(i);
if (view instanceof Button) {
((Button) view).setText("");
((Button) view).setTextColor(Color.BLACK);
}
}
If you still want to use foreach cycle, you must extend FrameLayout class and implement Iterable interface. But it's more work over nothing.
Related
Do you guys know if there's a proper manner to get all specific view types from the parent view as the title says?
I would like to get all the EditText views from my activity, so I wonder if there's a better way than using this solution get all views from an activity and then testing every view to check if it's an EditText or not?
Thank you for the help,
Florian
Approach 1 :
Let's say you named your edittext edittext_0, edittext_1, .. edittext_n. You can do:
ViewGroup vg = (ViewGroup) view;
for (int i = 0; i < n; i++) {
int id = vg.getResources().getIdentifier("edittext_"+i, "id", getPackageName());
edittext[i] = (EditText) vg.findViewById(id);
}
Actually the answers specified in the link given, are feasible if you have a large number of views, but if you want a specific type of view from a view/viewgroup, simply use findViewById method.
Example :
(in Kotlin) //Similar syntax in java
val view : View = findViewById(your_layout_or_any_other_view)
val childView : EditText = view.findViewById(edittext_id)
OPTIONAL READING
Optimised Answer for the answers given in link :
It is easier with Kotlin using for-in loop:
for (childView in ll.children) {
if(childView.id == your_edittext_id) //If required
//childView is a child of ll
}
//Here ll is id of LinearLayout defined in layout XML.
I dynamically create Buttons by entering a word. If I write "met", it appears on the screen - one Button per letter. The same thing happens for the next word I enter, and it appears below the previous word --- as shown in the image above.
When I click on a Button it turns green. My question is, what is the best way to disable the clicking of a row of Buttons. Meaning, if the user clicks on the 'm' in "met" I want the user to only be able to click on the Buttons in "met" and to not be able to click on any of the Buttons in "had", "goes", or "ran"
Here is my code:
EDIT
int size = enter_txt.getText().toString().length();
for (int i=0; i<size; i++){
final Button dynamicButtons = new Button(view.getContext());
dynamicButtons.setLayoutParams(rlp);
dynamicButtons.getLayoutParams().width = 130;
dynamicButtons.getLayoutParams().height = 130;
dynamicButtons.setTag("0");
dynamicButtons.setId(1);
dynamicButtons.setText(edit_text_array[i]);
dynamicButtons.setBackgroundResource(R.drawable.button);
button_list.add(dynamicButtons);
linearLayout2.addView(dynamicButtons, rlp);
dynamicButtons.setOnClickListener(
new View.OnClickListener()
{
public void onClick(View view)
{
int i=0;
LinearLayout ll = (LinearLayout) dynamicButtons.getParent();
for(i=0; i<list_of_ll.size();i++){
if (ll == list_of_ll.get(i)){
list_of_ll.get(i).setId(i);
break;
}
}
if(list_of_ll.get(i).getId()==i)
ButtonOnClick(view);
}
});
}
linearLayout2.setId(0);
linearLayout2.setTag("0");
list_of_ll.add(linearLayout2);
EDIT
I created a List of the LinearLayouts for each row of Buttons. The Buttons turn green if the id of the LinearLayout is set to 1. When I click on a Button I want that LinearLayout to stay at 1 and have all other rows/LinearLayouts set to 0 so they become unclickable.
Currently, every Button I click turns green even if it's in a different row. Can someone please help me solve this issue?
Why you don't set Id in the for loop so that you are able to refer and set the onlicklistener to null like jpcrow already mentioned.
Set Id like:
YourCreatedBtn.setId(i+1);
//Id's setted programmatically don't.
have to be unique... But they should be
a positive number (referring to the
android documentation)
And in your on click method simply set onclicklistener for specified Id's to null. Just a hint, hope it helps
Update regarding Thread-openers Comment
I found two simple ways but i would prefer the one which is not commented out in the buttonIsClicked:
LinearLayout llrow;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
llrow = (LinearLayout) findViewById(R.id.test_layout);
//Adding 5 Buttons
for(int i = 0; i<5; i++) {
Button mybtn = new Button(this);
//set LayoutParams here
mybtn.setId(5);
mybtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
buttonIsClicked(v);
}
});
llrow.addView(mybtn);
}
}
private void buttonIsClicked(View v) {
/*ArrayList<View> myButtons = llrow.getTouchables();
for(int i = 0; i < llrow.getChildCount(); i++){
myButtons.get(i).setOnClickListener(null);
}*/
for(int i = 0; i<llrow.getChildCount(); i++){
llrow.getChildAt(i).setOnClickListener(null);
}
}
It's just a simplified Version of your code, but i'm sure you will get the Content..
What if found out is, that you don't have to set the ID in both cases.. You can easily get all the child over
YourRowLinearLayout.getChildAt(starting from 0 to n-1-Views you added)...
I didn't found a way around the for-loop... But this small-little loop will not break your neck regarding to Performance..
The outcommented-code is the second Approach, finding all the Child over getTouchables which logically leads to an ArrayList and that's exactly the reason why i don't like it. You have to initialize an arraylist...... However, this also won't break your neck regarding to Performance but a penny saved is a penny got! ;) Hope it helps and everything is clear. Both of them work! Please mark as accepted answere if it fits your Needs...
You have to distinguish between the two rows, either add them to different ViewGroups or you can use View.setTag(int key, Object tag)
I'm making an app that stores results in a multiple textviews,
First, I need to get the views, they are 20 views named result 1, .... result 20.
how can i get them to an array of textview.
I found this method but it's too long
TextView [] results = {(TextView)findViewById (R.id.result1),
(TextView)findViewById (R.id.result2),(TextView)findViewById (R.id.result3),
(TextView)findViewById (R.id.result4),(TextView)findViewById (R.id.result5),
(TextView)findViewById (R.id.result6).....};
thank you for help
How you started is correct, now think about putting that repetitive code in a cycle.
For example design a method that will take as the input an array of your TextView resources, and using a "for" cycle find that view by corresponding id.
private TextView[] initTextViews(int[] ids){
TextView[] collection = new TextView[ids.length];
for(int i=0; i<ids.length; i++){
TextView currentTextView = (TextView)findViewById(ids[i]);
collection[i]=currentTextView;
}
return collection;
}
And then you use it like this:
// Your TextViews ids
int[] ids={R.id.result1, R.id.result2, R.id.result3};
// The resulting array
TextView[] textViews=initTextViews(ids);
if you have a handle to parent the layout that contains the text views, you can recursively discover them with a function like this,
void getTextViews(View view, List<TextView> textViews) {
if (view instanceof TextView) {
textviews.add((TextView)view);
else if (TextView instanceof ViewGroup) {
getTextViews((ViewGroup)view, textViews);
}
}
now call it like this,
ViewGroup topLayout = findViewById(...);
List<TextView> views = new ArrayList<TextView>();
getTextViews(topLayout, views);
TextView[] textViewArray = textViews.toArray(new TextView[0]);
this is quite a bit longer, but it has the advantage of not needing to change the code if you add, remove, or rename a textview.
IMHO, don't focus on writing less code, focus on writing clear code. the speed at which you type is rarely the limiting factor in your productivity.
I have a LinearLayout comprising of a few Buttons and I add this to my activity in the onCreate(..) method with setContentView(R.layout.myscreen). No surprises so far.
How do I get a reference to an iterator to these buttons? I'd like to add listeners to them but I'd rather not directly reference the Button's using their android:id.
Similar questions have been asked here and here but they don't quite answer my question.
Try something like this provide an id root_layout in xml to LinearLayout
LinearLayout mLayout = (LinearLayout) findViewById(R.id.root_layout);
for(int i = 0; i < mLayout.getChildCount(); i++)
{
Button mButton = (Button) mLayout.getChildAt(i);
mButton.setOnClickListener(this);
}
Where mLayout is object of you Linear Layout and Your activity must implements OnClickListener and here goes general listener
#Override
public void onClick(View v)
{
Button mButton = (Button)v;
String buttonText = mButton.getText().toString();
}
NOTE: For this to work properly you Linear Layout must only contains button no other views
You should take a look at my answer here.
In short. I'd assign the buttons a listener by setting the onClick attribute in the XML layout on each Button.
Inside of your Activity you'll need a public method like the one below which basically is what you want to do in your listener.
public void myFancyMethod(View v) {
// do something interesting here
}
If you want to go for accessing other elements you may try following syntax:
<ElementClass> <referencevariable> = (<ElementClass>) findViewById(R.id.<id_of_the_element>);
For Example:
TextView textView= (TextView) findViewById(R.id.t1); //I used t1 to refer my textview in the Layout.
This might work.
Then you can use these views with their inbuilt methods to perform as many as work you want.
I have a question that is driving me crazy.
I have a large number of buttons (10, more or less) on my screen, inside a TableRow.
I need to access them, and I had planned to perform through a loop.
Access to one, is very easy, adding this:
boton7 = (Button) findViewById (R.id.Btn7)
My question is, if you can dynamically set the id string (R.id.Btn7) to put in a can get the buttons for, and for example, change the color .... something like this:
for (int i = 0; i <10; i + +) {
Button eachBoton= (Button) findViewById (R.id.Btn + i);
eachBoton. setBackgroundColor (Color.Red);
}
That, of course, does not work .... my question is if anyone knows how exactly the chain can be mounted
R.id.Btn + i
to work.
Thanks a lot.
You can use Resources#getIdentifier() to get a resource identifier for the given resource name:
int resourceId = getResources().getIdentifier(
"Btn"+i,
"id",
this.getContext().getPackageName());
Button button = (Button) findViewById(resourceId);
Alternately you can prepare an array with all the ids you need and access elements of that array. This is more efficient:
private final int[] btns = {R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, ...}
...
Button button = (Button) findViewById(btns[i]);
Give an identifier to your layout ("layout" in the example below) and then iterate over all the touchable children by using getTouchables. If it's a button, change the color.
View layout = findViewById(R.id.layout)
ArrayList<View> touchables = layout.getTouchables();
for (View b : touchables) {
if (b instanceof Button) {
b.setBackgroundColor(Color.Red);
}
}