Finding the current layout-xml file in focus using code - android

I am working on a practice android project, and I am trying to implement polymorphism ideas into my program. So far, I have created two different XML layouts, one for tablets, and one for phones. They both have a button, but I want the button to do different things depending on which layout it is in. I am using the onClick property, and both layout's buttons refer to the same method.
In my buttonClick method, I want to find out which layout is is currently being shown, and I am trying to do it this way,
public void buttonClick(View ve)
{
View v = getCurrentFocus();
//According to the API, this method returns the current view,
//but the Log Tag says that it is null, which should not be the case.
Log.i(TAG, "Current View is " + v.getContentDescription());
//I want to control what happens polymorphically using the next if-else
//clause,depending on the layout, I think that this part would work if
//the above code works alright.
if(v.getId() == R.id.TabletLayout)
{
TextView myText = (TextView)findViewById(R.id.textView);
if(myText.getText().toString().contains("World"))
myText.setText(R.string.ayo_android);
else
myText.setText(R.string.hello_world);
Log.i(TAG, "changing words");
}
else{
Log.i(TAG, "Creating new Activity");
myText = (TextView)findViewById(R.id.textView);
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("screenText", myText.getText().toString());
startActivity(intent);
}
}
Thanks.

That's not the way to do it. If you want them to do different things, have the refer to different click handlers. If they're widely different they shouldn't even have the same id. The entire idea behind the automatic layout overrides is that the application should never need to care which one to use.

In addition to Gabe's answer, getCurrentFocus() will not give you the layout of the activity. If you want the layout of the activity, you can use
View v = (View)findViewById(android.R.id.content);

Related

How can I display a button in the onCreate method of an activity based on a given condition?

I want to display a button in an activity, but the text and background of the button are different if a specific condition is met by the user. How can I initialise the same button in the OnCreate method, having two different designs based on a condition?
Here Maybe this help
val btnGet = findViewById<Button>(R.id.btnGet)
if (id == 1){ //Your condition
btnGet.text = id.toString()
btnGet.visibility = View.VISIBLE //Make Sure in xml it is gone
btnGet.setTextColor(Color.parseColor("#bdbdbd"))
btnGet.setBackgroundColor(Color.parseColor("#ffffff"))
}else{
btnGet.text = id.toString()
btnGet.visibility = View.VISIBLE
btnGet.setTextColor(Color.parseColor("#FFBB86FC"))
btnGet.setBackgroundColor(Color.parseColor("#FF03DAC5"))
}
If you want the full code I will share it with you
Happy coding
1. You can change this properties in run time.
2. You can create two drawables files to set in the button background, but the text you still needing to change in runtime.
3. And you can use data binding in your xml file, using layout Data, like:
Google Link

Inflating Android list subviews -> duplicate IDs

I have some content in an Android app which is shown in a list. Each list entry has similar fields - let's say a picture, some text, and a text box. However, some list entries are different than others. The order of the content is based on the result of a server call.
The list itself needs to be fairly dynamic, and I'm currently using a linearlayout rather than a listview for a few reasons. My code looks something like this:
LinearLayout list = findViewById(android.R.id.list);
while (more content to add) {
switch (content type) {
case A:
View v = layoutInflater.inflate(R.layout.list_item_type_a, list, false);
EditText editText = (EditText)v.findViewById(android.R.id.edit);
// Do stuff with editText
list.addView(v);
break;
case B:
View v = layoutInflater.inflate(R.layout.list_item_type_b, list, false);
....
}
}
This works great. Except - when I put this in a fragment, and rotate the screen, now my app crashes because I have multiple fields with the same android.R.id.edit identifier.
I had thought this was a fairly elegant solution and the Android gods seem to disagree. Do I need to rip out the ID for all of my xml sublayouts? If I go this route, how should I grab references to the content?
So obviously, ListView or RecyclerView would be preferable to use here, but since you've stated you have reasons not to, I'd suggest that you disable automatic state saving for each of the views.
You can just call editText.setSaveEnabled(false), which will fix the issue, but have the side effect of not automatically retaining the view's state (e.g. input data will be lost). If you're maintaining this data yourself and restoring it on configuration changes or state restoration, this should be a totally workable solution.
I believe you could also just call setSaveFromParentEnabled(false) on the containing LinearLayout (although I haven't used that flag myself), which should disable state saving for any view in the sub-hierarchy. Same caveat applies.
I would suggest using a ListView instead of the LinearLayout and creating a custom adapter to fill the ListView. You could still have the list_item layouts that you have and then add them to the list in the newView method of your adapter. Pass your content type through a method, say getItemViewType(). Something like this:
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// Choose the layout type
int contentType = getItemViewType();
int layoutId = -1;
switch (contentType) {
case A: {
View v = layoutInflater.inflate(R.layout.list_item_type_a, list, false);
EditText editText = (EditText)v.findViewById(android.R.id.edit);
// Do stuff with editText
list.addView(v);
break;
}
case B: {
View v = layoutInflater.inflate(R.layout.list_item_type_b, list, false);
....
}
}
I think this problem occur due to device screen rotation
When the phone rotates and the screen changes orientation, Android usually destroys your application’s existing Activities and Fragments and recreates them. Android does this so that your application can reload resources based on the new configuration.
The most important aspect of handling orientation changes is saving state. In most cases this involves implementing the onSaveInstanceState method (this could be in your Activity, Fragment or both) and placing the values you need to save in the Bundle argument that gets passed to the method.
For more details and code examples...
Please read this article
If you have a dynamic list, you should be using a ListView or RecyclerView.

Show views currently focused (Even without layout selectors)

I'm trying to inspect a code for a very big Android (Amazon Fire TV) activity but i keep loosing the focus in the running app and i don't know what element is being focused.
I'm looking for a way (Wether it's an App, a developer setting - Show Layout Limits gets near - or something i can code inside the activity) to see what view is being focused, without having to change the layout (Selectors) of every single view.
What do you suggest?
Activity has a method called getCurrentFocus().
Maybe you could call hasFocus() on all the Views if the above doesn't work. I imagine the method would look something like this:
public View getFocusedView(View layout)
{
View focusedView = null;
// Note: I'm not sure if FOCUS_DOWN is the right one to use here
// so you may want to see the other constants offered
ArrayList<View> views = layout.getFocusables(View.FOCUS_DOWN)
for(View v: views)
{
if(v.hasFocus())
{
focusedView = v;
}
}
return focusedView;
}

Buttons using onClickListener

am new to android
I have seen many examples on creating buttons, but i just can't get what does each line mean :(
take the following piece of code as an ex.
connect = (Button) findViewById(R.id.button_connect)
connect.setOnClickListener(connectListener)
private OnClickListener connectListener = new OnClickListener() {
public void onClick(View v) {
Log.i("CONNECT PRESSED", "press")
// ....
// ....
// ....
};
what i know is that the first line Defines a button, but wht is findViewbyId?
i know the second line
but then when defining the listener, what's the log.i?
nd r "connect pressed" and "press" just labels for the button? f so why there r two for a single button...
You should have an additional Button connect; before those lines.
connect = (Button) findViewById(R.id.button_connect) // findViewById() in layman term it means, finding view by id. Which also means finding the view(button/textview/edittext) by ID(value you stated in your main.xml for the view. e.e. android:id=#+id/"")
connect.setOnClickListener(connectListener) //listens to a click when clicked
private OnClickListener connectListener = new OnClickListener() { //if button of android:id="button_connect" is clicked, Do this method.
public void onClick(View v) {
Log.i("CONNECT PRESSED", "press") //prints message in your logcat
// ....
// ....
// ....
};
If you still don't understand what does findViewById(), just think of it this way. View is man. Id is name. So in the end you are finding the man by name("Whatever this is")
In Android you normally define the layout of an Activity in an XML file. Each View element in a layout that you want to interact with in code needs an id. In you example the layout XML file needs to have a button with the id button_connect.
In the onCreate() method of an Activity you normally call setContentView() and pass it the layout you want to use in this Activity. E.g. setContentView(R.layout.my_layout); where your layout file's name is my_layout.xml.
The setContentView() method builds up the defined layout as objects and with findViewById(R.id.button_connect) you get a reference to a Button object from this layout whose id is button_connect.
Log.i() is simply logs the message "press" under the tag "CONNECT PRESSED" in the log cat.
It seem to be you didn't read basic things about android app development. Android Developers website providing information to learn android app development with good examples and tutorials. You are asking very basic things by just copying the code from tutorials.
Actually its not the right place for this kind of questions. First do practice by reading tutorials around the web.
Coming to your doubts regarding code you posted here, those are very basic things.
findViewById() finds a View by field Id, which is declared in XML layout file as below
Log.i() is LogCat info message displayed in your logcat window when debugging is enabled in your app.
in your example you probably have defined an xml layout file as the style of your activity with setContentView(R.layout.myXMLLayout);
If not, findViewById(R.id.button_connect) will fail.
R.id.button_connect refers to an id created in your xml layout.
There has to be a line android:id="#+id/button_connect" in a < Button > tag.
findViewById finds this Button (which is more genereally a view, which is why you have to cast it to a Button with the (Button) before findViewById(...) ). You then refer to exactly the button you've put in your xml.
Log.i("CONNECT PRESSED","press"); isn't necessary at all. It's just logging the press of the button and displays it in the log cat. It can be removed without any further impact. This is for debugging only and should be removed for any final (public) versions of your code.

android setBackgroundColor in runtime and other general confusion help?

i have a row of buttins created like this
i want to change the background colour at runtime in code.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout track1 = (LinearLayout)findViewById(R.id.my_toggle_container);
for (int i = 0; i<32; i++) {
ToggleButton tgl = new ToggleButton(this);
tgl.setId(i);
...
track1.addView(tgl);
this names the id of the togglebuttons 1, 2, 3... (i presume?)
i have an int variable called 'xBtn' that changes 1, 2,..
this is how i get a reference to the button using xBtn
String buttonID = ""+xBtn;
int resID = getResources().getIdentifier(buttonID, "id", "com.thing");
//find the button
ToggleButton tb = (ToggleButton) findViewById(resID);
//change its colour
tb.setBackgroundColor(Color.BLUE);
it crashes on the setBackgroundColor line.
it may be obvious to someone whats wrong and thats what im hoping
any help would be totaly ace ta
thanks
main.xml
<LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:id="#+id/my_toggle_container" android:orientation="vertical">
The id of your togglebuttons is gonna be a number from 1 to 32... However, trying to find the toggle button by id will return null because simply instantiating a new toggle button and giving an id wont help you. findViewById looks in the parent view for a child view with the specified id. If you havent added that toggle button with that id to the view, then findViewById will return null. I am 99.99% sure even without looking at the log, that it crashes because you are calling setBackgroundColor on a null object.
In other words, the id that you set a view to is only relevant once the view is actually added to a parent view. In your case you are probably trying to add these toggle buttons to your main content view, in which case you need grab hold of that view that you used for setContentView and call addView on that view and pass in each new toggle button. Note that this will probably not look right unless you also specify layoutparams for the togglebuttons.
EDIT
If thats your entire main.xml, then you've got other issues. Post the full xml file. In any event, you still are going to have to do what I've said, which is to grab hold of the view or a child view of that view and then add the toggle buttons to it via addView (after giving the togglebuttons their proper ids). Once the button has been added, then you can find it. Note though that if you're gonna add the toggle buttons to a child view of your main view, then you'll likely have to grab hold of that child view and call findViewById on THAT.
For example, you can do a nested call like this. findViewById(1) <--- gets you the LinearLayout or whatever inside of your main content view, then once you have that you can call addView on it. So LinearLayout ll = (LinearLayout)findViewById(someNumber); ll.addView(tb);
Try to use the method setTag() , and then you can get all your ToggleButton by using : findViewByTag();
Perhaps tb is null? Could you check that out?
To expand on what LuxuryMode said... What gets an ID INTO your java is inflating it via setContentView and setting it as content. That's why it's ok to have overlapping (duplicate) IDs in different layouts. You can have #+id/submit_button in layout1.xml and in layout2.xml and the Activity will get you the object via findViewById(R.id.submit_button) based on which one you have loaded into setContentView() at any given moment.
So, we're all guessing that you're probably not setting the content view and hoping that the code will find your object in your non inflated XML, which it won't. Which would lead (as everyone has guessed) to you now dealing with a null object, which you obviously can't set a background color on.
I know it gets confusing cause you have the XML RIGHT THERE!!! But the reality is that the xml isn't "alive". It's just stuff for you to look at until you have tasked the Application with inflating it and converting all of it into Android objects of some kind. A lot of the time this is done mostly transparently to you, so, it's easy to forget that none of these things really exist.
It's very likely that tb is null, because findViewById() didn't go as you expected.
You can verify this by surrounding the erroneous line with try.. catch block:
try {
tb.setBackgroundColor(Color.BLUE);
} catch (Exception e){
}
and watch for the message of e. It's likely to be null pointer exception.
In fact, I think you should not use getResources().getIdentifier(buttonID, "id", "com.thing") in the first place. It seems to me that all these resources are continuously numbered in R file, thus you should simply get the first id (as an integer), and then increment on that.
That is, you should do things like:
// The following code is not tested; I just wrote it here on SO.
for (int resID = R.id.button1; resID <= 32; resID++) {
ToggleButton tb = (ToggleButton) findViewById(resID);
tb.setBackgroundColor(Color.BLUE);
}
this should make all 32 buttons blue.

Categories

Resources