I can't get my button to work on my second layout (Android) - android

I've spent 8 years programming and for 8 years I've been pretty happy, but after using Android Studio for two weeks I already want to
So here's the deal. I made 2 layouts. One is the default, named activity_main.xml, the other is named graph_layout.xml. They are both ConstraintLayouts (but the same issue occurred when I tried making graph_layout a LinearLayout or RelativeLayout, so we can rule that out as a factor).
In activity_main, there's a button with the ID, graph_button_1. When I click it, it prints to the console "AAAAAAAAAAAAAAAAAAAA" (but with more A's) and switches from activity_main layout to graph_layout. As it should, that's precisely what I designed it to do.
Now, here's the problem. I also have a button in graph_layout with the ID, calc_button_3. When I click this button, it's supposed to print to the console "AAAAAAAAAAAAAAAAAAAAA2" (but with more A's) and then switch from graph_layout to activity_main. It doesn't do that, though. It prints to the console a little message that, "yes, you did click the button, here are all the details of how you clicked that button" (I'm paraphrasing), but it does not print "AAAAAAAAAAAAAAAAAAAAAAA2" to the console, nor does it switch back to activity_main. (If you're wondering, the AAAAA message is just to see whether the setOnClickListener functions are actually executing).
Speaking of which, here's what the setOnClickListener does for calc_button_3:
//final Context context = this;
calcButton3.setOnClickListener(new View.OnClickListener() { //I know I can use lambda funcitons, but I wanted to play it safe
#Override
public void onClick(View v) {
//Intent intent = new Intent(context, MainActivity.class); //This was one of the solutions I found online. It does not do anything.
//startActivity(intent);
System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2");
setContentView(R.layout.activity_main);
}
});
To be fair, I'm a step in the right direction. Before, this function made my app crash. Now, it just does nothing. So...that's a little better, and I'd like to thank the LayoutInflater class for making that possible. I'd also like to point out that I'm willing to supply you with any code or extra information you might want to see. I'd send the whole MainActivity.java file if I could, but I know from experience the longer I make my question, the less likely people are to answer, and it is a VERY long file.
I've scoured the internet for a solution to this, and while I've found people with a similar problem, none of their solutions worked for me.
Your help is greatly appreciated. Thank you.
Below, I will attach any code or additional info anyone in the comments asks me to give them:

You have to start a new activity using intent or if you want to use the same activity then use fragments. and replace fragment layout on button press. but you can not directly use setContentView();

All setContentView(R.layout.activity_main) does is inflate that layout file into its hierarchy of View objects, and display that in the current Activity. You're still in the same Activity, you've just changed its contents.
When you say you're doing this:
In activity_main, there's a button with the ID, graph_button_1. When I click it, it prints to the console "AAAAAAAAAAAAAAAAAAAA" (but with more A's) and switches from activity_main layout to graph_layout.
does that mean you're "switching" by calling setContentView there too, instead of starting a different Activity that displays graph_layout?
If so, and all your code for both layouts is in the same Activity, then your problem is probably related to the fact you're replacing your Views with a new set of objects when you call setContentView. If you set up your buttons like this:
// a Button from your current view hierarchy gets assigned to this at some point
val someButton: Button
// just use the lambda, it's literally the same as creating the object under the hood
someButton.setOnClickListener {
// do a thing
}
And then later you call setContentView(R.layout.some_layout), then whatever Button object someButton is referencing is no longer on the screen. So you can't see it, you can't click it. If you just inflated the same layout as before (creating an entirely seperate set of View objects) then there's another button in the same place - but you haven't set a click listener on it, so it doesn't do anything.
So if you are going to go replacing the view hierarchy like this, then you need to perform your View setup (like assigning click listeners) when you create those new views. If you just set things up when the Activity starts, then it's only applied to the view hierarchy in use at that moment. As soon as you replace it with setContentView, that stuff is gone.
So you could write functions that "switch" to one layout or the other by calling setContentView and then applying the click listeners. Generally speaking though, this isn't how you normally do things in Android. The old way would be to create separate Activities for each screen, a more modern approach is using Fragments which can be swapped out manually or by using something like the Navigation library.
Either way, both those approaches involve configuring your Activity or Fragment once during setup, making buttons do this or that, and then you're done. Everything's neatly separated and self-contained, instead of you having to swap views out and rewire everything according to the state you want to display. That's just complicating things, and it'll get much worse if you start adding more screens you have to juggle!
I'd recommend at least taking a look at the Fragments guide, or the Navigation component if you have time. The latter has more to learn, but it also handles a lot of complexity for you. It would help to at least have an understanding of the usual way of doing things, anyway!

Related

What's the proper way to return a result from an activity to a specific view?

New to Android. Trying to understand the technical downside of a design.
I have an ItemSelectorView which has both an availableItems collection as well as a selectedItem property. The latter is displayed at runtime along with a chevron letting the user know they can change it.
Functionality-wise, it's similar to a spinner except rather than showing a pop-up with the choices, it launches a second activity called ItemSelectorActivity which shows all of the available items from the ItemSelectorView which launched it, as well as helpful information about what each option means as well as the ability to search and filter.
When a user selects one, their choice is then returned back to the originating ItemSelectorView via a trip through MainActivity's onActivityResult override. The override then figures out which ItemSelectorView it's responding to and forwards it along.
However, I really didn't like the way MainActivity had to insert itself into the process just to get the result from ItemSelectorActivity. Plus, if ItemSelectorView was used in a fragment, things become more complex trying to forward the information to the correct view.
Because of this, I instead changed ItemSelectorView to ItemSelectorFragment which can override its own onActivityResult making it, not its owning activity, responsible for updating itself with the selected result. This means it's essentially completely self-contained now.
While this seems to work wonderfully--with this change a user only needs to place the ItemSelectorFragment somewhere in their layout and set the available and selected items--a veteran Android developer here said using a fragment like that was wrong and I should have stayed with a view because of the overhead of fragments.
But going back to a view means I'm back to having to get MainActivity involved again, making this much more complex to actually use.
So what is the technical down-side for using fragments like this? I thought that was the entire point of why they exist. And if I am supposed to use a view, is there an easier way to get a result from ItemSelectorActivity?
If I understand you correctly, your view is starting an activity (ItemSelectorView starts ItemSelectorActivity). But views should be dump in Android. They should display, nothing more.
So a view should never start an activity. A view can contain a list of items maybe, but these items should be views and nothing else. Usually we use an Adapter for that: a middle man between the items to be displayed and the views that are created to represent them on the screen.
You could look into MVP to do this in a proper way. Or maybe MVVM and android architecture, if you like that better.
To answer your question, using a fragment for your use case is a better approach then a view and there is not that much overhead at all.

Opening an activity within a View in Android

I've recently started developing Android Apps, and whilst the model is making more sense the more I look at it, I cannot do something (nor find any reference material on it) which to me seems quite simple.
I have an activity which has five buttons along the bottom, and a blank View taking up the rest of the screen. I want, upon clicking these buttons, for an activity to be opened in (and confined to) this view. I can get a new activity running without incident, but this opens in a new screen.
If anyone can show me an easy way to launch a (sub/child?) activity within a view which is defined in the parent activity's layout xml file - equally, it could be created in the parent activity - you'd really be doing me a favor!
I'd recommend taking a look at TabHost. The tabhost is an Activity itself, and the sub-views are all Actvities as well.
Here is a good tutorial that'll get you going very quickly. There is a more work to create (optional) icons for the tabs (also describe in the tutorial).
Hope this helps.
Edit* You mentioned buttons being at the bottom of the screen. Take a look at this SO Question
You can achieve that by using an ActivityGroup... here is a simple example which shows how to do it using a TabActivity:
http://web.archive.org/web/20100816175634/http://blog.henriklarsentoft.com/2010/07/android-tabactivity-nested-activities/
Of course, you will have to change the code since you are not using TabActivities. Just take a look at the getLocalActivityManager and getDecorView methods that is what you will be using.

Android Development: Switching between Views without losing onClickListeners

On my application I'm developing, the main.xml layout (the default layout of my app) has a few buttons that have been assigned onClickListeners (not the implementation way).
One of those buttons I want to have the ability to take you to another view. On the other view (preview.xml), there's another button that takes you back to the main.xml view.
I've used setContentView in the onClickListeners of those buttons and this works fine so far, but after you click the button that takes you back to main.xml, the buttons on main.xml have lost their onClick functionalities.
How can I get this to work right? I presume using setContentView isn't the right way to do this.
Your best bet, at Konstantin says above is to use Activities, as you will come across these a lot whilst developing for android. you can read about them here Activities. I assume you want to pass something onto the preview.xml page? If so, I'd recommend either putting it as an extra in the Intent used to start the activity (see the link) or creating a static reference in the activity (which you set before you launch it).
I'd say use two different activities and switch between them. Another option can be ViewSwitcher.

Modifying application workflow to use TabActivity

This question actually has two parts.
The first part:
I've been developing my first app for a couple of weeks now. I have 5 screens and everything seems well. However, I'm considering changing the app's navigation to a TabView.
I haven't delved much into it, but I'm hoping someone can save me a little bit of time. It seems that people don't generally place Activities inside each tab. They simply point the tab content to a View. This is where my major setbacks are. 1) I already have Activity classes full of code and 2) I can't quickly guess how the structure of an app using TabView looks. For example, where do I put the handler code for clicking a button on a View? Does it all just get dumped into the TabView Activity somehow?
What I would like is if you could please give me a quick synopsis of what I'm looking at doing, answers to any questions you think I may have, and point me toward some resources for creating TabView applications. A quick Google search really just shows me how to create a TabView Activity and add a couple tabs to it. The code doesn't go any deeper. For example, say I have a layout xml to show in one of my tab's content pane, where does the code go for clicking a button I have in that layout?
The second part:
I've added a TabActivity to wrap the Activities I currently have in. At the moment I have Activities populating the content of my tabs (though ultimately I'd like to do this in the most efficient fashion, which doesn't seem to be having Activities be tab content). I've noticed something rather annoying. My MAIN Activity is an Activity I wrote for my user to log in to their account. After logging in, they are taken to my Tab Activity. Here is what happens:
When I am on my Tab Activity and I "minimize" the app by clicking the Home button and then launch it again, I don't get taken back to the Tab Activity. I get taken to my log in Activity. Why? I don't have the launchMode of my Tab Activity set to singleInstance... or is it singleInstance by default? How can I make the app re-launch showing the Tab Activity (ideally by setting some parameter, assuming I'm doing something wrong, and not having to save this data off somewhere and reading it and programmatically telling it what to go to)?
Thank you for all your time and help
I don't have a comment on the advisability avoiding the use of sub-activities in TabActivity. As for handlers -- if you aren't going to embed views instead of activities, then all the android:onclick type handler settings in your layout XML will call methods on the TabActivity. This is because they go to methods on the views' Context, which is the generally the nearest containing Activity. If you want to split your code up further without using Activities, I believe you'll have to use findViewById calls on the tab content views after you've set them up, and bind the handlers manually from there in your code.

Activities, Views and Dialogs in Android. Proper application structure for game

I was in the midsts of tinkering in android with the goal of trying to make this small exploration game. I actually got pretty far so far: a nice sprite system, a title screen with a main menu that is all in game code (no UI buttons or anything) that launch various activities. An activity that loads this cool map view, that when clicked on will load up another view of a more detailed "zoomed in" action part of a map. It all works pretty well but now I am left wondering how well I am going about this.
(What happens to a view when you instantiate and then move the set the context to a new view? I am guessing as long as the activity is alive all the instantiations of various views that an activity uses are still good? And in an activities onPause is when id have to save the data thats changed in these views to persist the state in the event the user quits the game etc.. ?)
I have three menu options at the start of the game. The main one is:
New Game
The new game, I launch my main map
activity that can launch three views:
First two are a loading screen for
the second, a map screen.
Third view is a more detailed action
orientated part that uses this sprite
engine I developed.
It all works pretty good as in the map view you click on a cell it tells the Calling Activity through a listener to start the detailed action view, and passes in the ID of the cell (so it knows what objects to load in the detailed view based on the cell clicked in second view). (This took me awhile to figure out but someone helped here on another question to get this.) Reference that helped me on this part here. I also used the various information here on ViewSwitcher.
I got even a yes no dialog box in the second view that asks if they really wanna goto that cell when they click on it, a yes tells the calling activity to set the new view. What helped me to get this working was this reference here. I also had to fiddle with the calls to getContext and that, I am still not 100% sure what getResources and getContext do for me.
So is it bad practice to call and load a dialog from a view? If it is, then I don't understand how if I have an event in the view that needs to pop up a dialog how I do that? Call back to the activity and let the activity handle it the dialog response and then call a method on the view for the response?
So far all this works great, I did have a bit to learn about threads too. I spawn a different thread for my MenuView (handles the detection of button clicks and responses), my CellMap view which handles the cool big map that users can click on to see the indepth view which is my SystemView view.
So basically the activity call list is like this:
Home.Activity -> ScrollMap.activity which listens to CellMap wher ethe Yes/No dialog apperas (in the view of CellMap) and if the answer is yes to the question, then the onTouchEvent starts up the SystemView view using
private CellMap.MapClickedListener onTouchEvent=
new CellMap.MapClickedListener() {
#Override
public void onMapClick(int id) {
setContentView(new SolarSystem(theContext,id));
}
};
To help anyone else, that listener had to be defined in my CellMap class. Then in the ScrollMap activity when I am about to start the CellMap I just call a method to CellMap sets the map click listener. So far this is the only way I have been able to get data from a dialog (in this case a it was clicked so set the new view) back to the calling activity. Is this proper practice?
Now my biggest question is, I have a playerObject class I want to initialize on new game event (I know how to detect that push) and that then is available to any view in any activity for the life time of the cycle. So far the game activity has just two (3 if you count the loading progress bar) views. I want to get the players name, is that another activity or view? I cannot find a decent tutorial of just how to make a simple input dialogg box that would return a string.
How do i go about passing this stuff around? After I get the players name from wherever that edit box is to be loaded, I want to set the players name in the class and pass that class instance off to another view or activity so they may get at that data. Everything I have searched on this seemed like overkill or not the right way. Whats the best way to pass this "playerClass" around so that I can access it from other views (to say display the players name in every view).
I also have my Home Activity that waits for an onClick on 3 buttons, it then launches their activity that shows the view. I realize a continue game and new game are the same activity and will just change in data loaded off the drive to restore a save game. When the new game button is clicked I would love to get the players name they want to use and of course set the member of the playerClass to this name so it persists.
Where do I call (an edit dialog is it?) the edit dialog from? (more over how do I build one that can take an okay button and input from keyboard etc). Id also like to make it pretty, maybe I could have a simple view that has one edit box in it and a nice image background (though I haven't figured out how to place the edit boxes to fit nicely matching a background i draw for it. I guess id like an edit dialog I can skin to look how i want it to and fit the look of the game).
I am actually kinda happy what I got so far its looking not to bad, just not sure about some specifics like getting user input for a name of the player. Storing that information and passing it then to other activities and views.
Is it better to have one GameMain activity, and a ton of views:
Map view
Character sheet view
inventory view etc etc?
Or Should there be diff activities in there somewhere as well?
You've written a lot here, so I'm go gonna go ahead and answer the questions I think you're asking.
First, how can one share information between activities and views? If you're just sharing it between views in a single activity, store it in the instance of the Activity subclass.
Sharing between activities requires a little bit more. Instead of using an instance of the default Application class, you can create a subclass of Application and use that instead. Put your data in fields of that subclass. To tell your app to use your subclass, modify the app manifest like so:
<application
....
android:name=".YourAppClassNameHere">
....
</application>
As for getting user input, the simple answer is use the built-in EditText view. since you seem to want to give your game a more "custom" style, though, you may need to go about creating your own editable textbox. That and buttons should allow for most sorts of basic user input.
Now, good practice vis-a-vis activities and views. I'm not aware of a standard for this, but when designing I generally try to think of activities as more conceptually separate elements, whereas views are conceptually interwoven. the line between the two is dependent, in part, on the scope of the app; an app with a narrow focus can afford to break more actions down into different activities than can one with a much broader focus.
Your "GameMain" example is a bit on the fence, but I think you've made the right choice: the activity is "playing the game," as opposed to a menu or high-scores table, and the views present different aspects of the game being played.

Categories

Resources