sexta-feira, 12 de outubro de 2012

How to navigate between screens in Android


Hello everyone.

Up to this topic, we have learned how to install Android, create a project and even create fine layouts. What next? So far, in all examples seen was used at most one screen for example. The next step to be taken is to learn to navigate in more than one screen in the same application.

On Android, each screen is a Java class that extends the Activity class. To navigate between more than one Activity, we use the Intent class. If we are in an Activity and want to go to another, we have to call an Intent (ie have the "intention" of changing from one screen to another).

To understand the concept of Intent, we will create three very simple examples that basically pass through multiple screens of the same application. In the 1st example, we will create a simple transition from one screen to another. In the 2nd example, we will create a transition from one screen to another where the source screen sends a variable to the target screen. In the 3rd example, we will create a transition from one screen to another where the target screen returns a value to the source screen. This post will be divided between these three examples.

Simple transition from a source screen to a target screen
In Android, when we create a project in Eclipse, the AndroidManifest.xml file is generated, which is a configuration file where we report various informations, such as which screens exists in the application, which is the minimum and maximum API of the Android API that the application may run, among others. So, the first step to be taken in the creation of our example is to tell the AndroidManifest.xml the screens that we use in our application. Suppose we have 3 screens in our application: Screen1Activity.java, Screen2Activity.java Screen3Activity.java (is advised on Android to have the name of an Activity with the posfix "Activity"). So we need to declare them in the AndroidManifest.xml file, as shown below:



Agora que já temos as Activity's declaradas no AndroidManifest.xml, o próximo passo será criar o layout de cada uma dessas telas. De início, criaremos algo bem simples, como uma TextView sendo mostrada no centro da tela. Algo como isso:



For each screen, the parameter android:text="@string/screen1_title" shall be adjusted to the proper names (for Screen2 for example, the parameter is android:text="@string/screen2_title", and similarly for Screen3).

Then we need to create the Activity's of these screens (Java classes extending the Activity class). They basically follow this model:



Now that we created all our screens, its layout's, and declared all in AndroidManifest.xml, we can finally deal with the Intent's, allowing us to navigate among these 3 screens.

To navigate between screens, we need to create a user input device to select it when this transition occurs between screens. The best device for this case is to create a Button that, when clicked, change the current screen of the application. For that, we'll create a Button in Screen1Activity.java and other Button in Screen2Activity.java. The idea is that the transition occurs from the Screen1 to Screen2, and from Screen2 to Screen3.

Modifying the layout of Screen1, we have the following content in the XML file:



And it's layout will be as shown below:



Now, we need to map the id of the Button in our Activity (as is taught in the previous post). Modifying the structure of the source code of the screen Screen1Activity.java, we have the following content:



Now, we just need to implement the call to Screen2. For we call another screen in Android, we use an Intent. The syntax of a call to a class Intent is shown below:


The constructor of Intent class is: Intent intent = new Intent(packageContext, cls). The argument "packageContext" is the context of the current Activity. The argument "cls" is the class of Activity for which the current Activity want to go. In the image above, the values ​​of these arguments are, respectively, "Screen1Activity.this" and "Screen2Activity.class". So, we have the "intention" to migrate from Screen1 to Screen2.

The complete source code of Screen1Activity.java is shown below:



Now we simply need to adapt this source code for Screen2Activity.java, to have implemented the transition between Screen2 and Screen3. And it's done! We'll have implemented an application with several screens, and the transition between them.

Now, we will see how to implement a transition between two screens in which the target screen will send data to the target screen.

Transition from a source screen to a target screen with sent information between them
In the transition above, we used the method startActivity() to make the transition between screens. However, it was an easy transition, without sending information. This time, we'll send information from one screen to another. To perform this kind of task, we'll use again the method startActivity(). However, we'll modify a bit it's structure, as shown below:



The above image is the updated content of the event onClick(). What has changed here is that was included a Bundle on the Intent that calls the next screen. In Android, Bundle is the class that stores what is sent from one screen to another. This class has several methods. In the image above, we can see the method putString(). This method receives the "key" that will pass the string to the next screen, and it's value. The key is a value (always String) which we use to obtain, in the target screen, the passed data from one screen to another.

Now that we transmited data from the source screen to the target screen, we need to capture these data in the target screen (in this case, in Screen2Activity.java). This is done through the method getIntent().getExtras(), which returns a Bundle. Below is shown the source code of a custom method that performs this task.



Some comments need to be made about the image above:

  • We have to check if the extras are null or not. This is very important because we can call a screen from different parent screens. For example, both Screen1 as Screen2 may call Screen3. And if Screen1 send data to Screen3, the extras from the image above won't be null. But if Screen2 don't send data to Screen3, the extras from the image above will be null.
  • mTextView is an attribute of Screen2Activity.java, which is nothing more than the TextView of this screen. As we are getting data from the previous screen, to check whether these data come from Screen1 to Screen2, we'll update this TextView.

The complete source code for this screen is shown below:



And it's done! We already know how to pass data from one screen to another. Following this topic, we will see how to implement a transition between two screens when the target screen returns a value to the source screen.

Transition from a source screen to a target screen, with information sent from the target screen to the source screen
In the above transitions, we used the method startActivity(). This time we will use another method: startActivityForResult(). With this method, the destiny Activity can return informations to source Activity. This is quite useful in some cases.

For example, suppose we have a Screen1, that can call either Screen2 as Screen3. This case, if Screen1 was a customer base, Screen2 a customers deletion and Screen3 a customer registration, when we open Screen2 or Screen3 and perform some operation, we will be redirected to Screen1. But in this screen we need to know whether the deletion/registration was successful or not. In this case, we need to send some feedback to Screen1, from the end of execution of screens 2 and 3. This is done with the method startActivityForResult().

Below is shown a basic example of this functionality. The idea is that an Activity is called in Screen1, and that the daughter Activity returns an information to Screen1. The Screen1 may call both Screen2 and Screen3. This information will be captured by Screen1 through the event: protected void onActivityResult (int code, int result, Intent intent). Let's see our example.

Below is shown the XML layout of our screens.







And the source code of Screen1Activity.java:



And now, the source code of Screen2Activity.java. Screen3 will be similar to this screen.



Now, let's run this example, to set right all that was said above. Clicking on the "Go to Screen 2," here's what happens:



Now we are in Screen2. Clicking the "Return to previous screen" button, here's what happens:



Basically, what happened was that the Screen1 received a return from it's child Activity. Thus, we can identify which of the screens was called by Screen1.

And it's done! We already know how to pass data from one screen to another in every possible way. But before we close this topic, we will talk about a very useful property layout in Android.

When a button is clicked, the ideal would be the user to have a feedback of what happened. In other words, when the button is clicked, stay in one color. When loose, stay in another. Thus, the user will know if the click event of the button was activated or not. We will implement this in our example.

Initially, we will implement the XML file that "animates" the button. Let's call it "button_behavior.xml". Your source code is:




So, when the button is clicked, a drawable will be called. When he is not clicked, another drawable will be called. Now, we need to understand the content of the mentioned events of the above file (pressed_behavior.xml and normal_behavior.xml). Below is shown the source code of these files:





These files have some parameters:

  • gradient  This parameter selects the color the button will have. It can have 3 different mixed colors. For our example, we will have an identical color gradient (the same for each gradient option) in each drawable.
  • corners  This parameter creates smooth contours on the button. In our case, we have the button corners slightly rounded in a size of 3dp.
  • stroke  Parameter that provides an edge on our button. Here, we have a black border of 1px size.

NOTE: There are other parameters besides the three above. But they will not be seen this time.

Now we need to turn this animation on the buttons of our example. To do this, simply include the parameter android:background="@drawable/button_behavior" in each of the buttons on our application. By doing so, we will have much more stylish buttons, which are very intuitive to the user.

-----

And here ended another blog topic.

If someone has a question, suggestion or criticism, feel at ease.

quinta-feira, 11 de outubro de 2012

Interacting with the Layout


Hello everyone.

Now that we know how to install Android on our machines, create a simple application and do basic layouts, we will learn to create layout's that interacts with the user. This interaction is basically done through the parameter android:id. Through this parameter, we create an identifier for a component of the XML graph which can be mapped directly into Java classes containing the source codes of our application.

To use it as an example of this interaction, was created a test layout, whose XML code is shown below.



And it's layout is shown below.



In this layout we have a EditText, a TextView and a Button. We will use all of these components in our example.

What we will basically do is get a text entered by the user in the EditText, and verify if it content is null or not. If is null, a message appears on the screen, alerting the user. If not, the contents of TextView will be updated with the typed value.

To get the text typed by the user, we need to map in the Java class each component id (contained in the XML). On Android, this mapping is done through the method Context.findViewById(int id), which receives an id from the XML and returns an object, which is nothing more than the mapped XML component in the Java class. As all Activity class inherits from Context, we won't need to call the Context as the prefix of the method findViewById().

Below is showed how we mapped the EditText of our XML into the Activity (screen) MainActivity.java:



As the method findViewById() returns an object, we need to convert it to it's corresponding component. In this case, EditText. Using this method, we can map the other components. To keep our source code organized and didactic, we will group these components into a single layout method, called on the event onCreate(), as is shown below.



To keep the code even more didactic, were defined Attributes in our screen. Attributes are variables that will be seen in the full scope of our screen. In other words, are the "global variables" of our screen. On Android there is a pattern to indicate variables which are attributes. This pattern is to use the character "m" as a prefix of the attribute variable. Note that the attributes of our screen have this prefix.

Through the method mapComponents(), we mapped the graphical components of our screen. Now, the next step in the specification of our example is to verify the content of the EditText. However, such a check should be made only when the button is clicked.

In Android, when a button is clicked, the onClick() event is called. However, this method needs to be implemented. There are two ways to implement this method:


  • Implementing the method OnClickListener in the header of the class, like shown below:


  • Implementing the method directly after the button has been mapped from the XML Activity, as shown below:


In both cases, what will be performed after the button be clicked shall be within the method public void onClick(View v). Then, we will check the EditText content (whether it's null or not) within this event. The updated code of our Activity looks like this:



The message to be shown on screen is invoked by the component Toast. This component shows on the screen, for a brief period (Toast.LENGTH_SHORT or Toast.LENGTH_LONG), a message. Notice that the text of the TextView was modified by the method mTextView.setText(content). This is one of several methods that a TextView have. Most of them is just a association of some parameter with this component in XML. For example, in XML we have android:text="text", and in Activity we have textView.setText("Text"). In XML we have android:visibility="gone", and in Activity we have textView.setVisibility(View.GONE). And so on.

Now, we will create a slightly more complex example, which involves a very common practice in Android: show or hide parts of the screen, depending on the value of a given parameter.

For this example, will be created another component in our layout: a TextView that only will be shown when the button is clicked. If the button won't be clicked, this TextView will stay hidden.

The generated XML is shown below:



And the generated layout:



In the above XML, the TextView is unlocked only to demonstrate how the layout will be at the end of the application execution. But for our application works according to the proposed idea (unlock a component of the screen), we must include the parameter android:visibility="gone" into the LinearLayout that contains the TextView.

Now we need to create this component unlocking behavior in our Activity. Modifying the source code, we have the following:



Now we can run our application. To do this, simply click on our project with the right mouse button:



And then click "Run As" and after, "Android Application". Now, an emulator will be opened.

NOTE: So you can choose which exact emulator opens, we modify the option of running the application. This can be done through the "Run Configurations..." option, as shown below.



Once inside this option, we need to click on the "Target" tab, and then on "Manual" option.



Now we can run our application and choose a specific emulator. Just choose the options "Run As" and then "Android Application". Now, we get the following screen displayed:



After choosing an emulator, our application will begin to be loaded into the emulator. After some time, finally our application will be loaded into the emulator, and we'll have the following situation:



Now we can test the implemented functionality. For this, we'll click the button without entering anything. Doing this, a warning message appears on the screen:



We have to enter something in EditText, otherwise this message will appear. Having typed text, we'll click the button. Here's what happened:



Basically what happened was that when the button was clicked, the TextView property Visibility was changed from GONE to VISIBLE. This practice is very useful in layout creation. For example: in a Client Manager, we must enable the City and State fields only when the Country field is initialized.

-----

Well, we came to the end of another topic.

If someone has a question, suggestion or criticism, feel at ease.

Layouts

Hello everyone.

Now that we know how to install Android on our machine, and how to create a simple application, we will learn to create layouts in Android. In Android, layouts are created using XML files with a very rigid structured and standard language, but also very simple and intuitive, due to the excellent structure created by Google.

There are several types of layout in Android: FrameLayout, LinearLayout, TableLayout, among others. In this post, we'll cover basically the 3 layouts cited in this paragraph.

FrameLayout
The FrameLayout is the most basic layout on Android. In this layout, we have only one layout structure stored. However, such structure may be another layout. This layout is often used in generic layouts, such as tabs and screens whose layout changes throughout it's execution. We will use this layout as a basis to teach many basic concepts of layout in Android.

For example, in Android there are various types of graphic components:


  • TextView → Displays text on the screen. It's definitely the most used graphic component in Android.
  • ImageView → Shows a picture or just a window on the screen. Every time you need to show a picture or a colored window, this component is used.
  • EditText → The above components only shows informations on the screen. But EditText gets a text typed by the user, which can be used to interact with the Android application.
  • Button → This component is one of the most common in any layout system. In this component, an action is performed after a click be given.
  • CheckBox → A component that basically has two values​​: true or false. Commonly used to represent the system settings.
  • RadioGroup → Quite useful component to show several options listed on the screen, where only one of them must be clicked. Widely used in multiple-choice questions.


And there are several parameters for each component in a graph layout in Android. To fully understand how those parameters, below is shown the use of some of these components in a FrameLayout. Below is shown the source code that creates the XML layout.



And the generated layout.



In the source code above, we have some parameters, which are explained below:


  • android:layout_width="match_parent" → In creation of layouts in Android, we always call a parameter using the prefix "android:". In this case, the last word of the parameter is "layout_width". This parameter defines the width size of the screen we are creating. This size can be a fixed size (in pixels, pixel density, or other formatting units) or expandable sizes. In this case, it hass a expandable size. There are 3 expandable sizes in Android:
    • fill_parent → With this option, the parameter size is maximum (ie, the current screen size). For example, if the mobile phone screen or tablet that we're dealing is 800 x 600 pixels, if we have in a FrameLayout the parameter android:layout_width="fill_parent", the width size of the screen we are creating will be 600 pixels. Starting from API 8 (Froyo, Android 2.2), this option was discontinued, and it's operation became the "match_parent" option.
    • wrap_content → With this option, the parameter size will be minimal, based on the child components of the current layout. For example, if we define the width of the current layout with layout_width parameter, as follows: android:layout_width="wrap_content", we are indicating that the width size of the screen is the size of the child component of this layout. In the case of the XML we are analyzing, it's child component is a TextView. If, for example, this TextView has a size of 20 x 20 (height x width) pixels, then the size of the layout is the same. That's what makes wrap_content. If we have fill_parent instead, the layout size wouldn't be 20 x 20 pixels, but 800 x 600 pixels (equivalent to the size of the mobile phone screen).
    • match_parent → Keeps the size inherited by the parent component. If there is no parent component, the size will be maximum (ie, the screen size). In XML we have a TextView and its parent component, which is a FrameLayout. If we put in the TextView parameter android:layout_width="match_parent", the width of the current screen will be the same width as the FrameLayout.
  • android:layout_height="match_parent" → This parameter defines the height of the screen that we are creating.
  • android:gravity="center_horizontal" → This parameter sets the alignment of the components of this layout. In this case, the alignment will be centered and horizontal.
  • android:text="Example" → This parameter defines the text of the current component.

Well, many concepts have been explained above. To understand them better, there is no other way than pick the options of each parameter and test. For example, here we have the same XML from above, but this time with the parameter android:gravity component from the changed TextView, from "center_horizontal" to "center_vertical".



And below we have the same XML as above, but this time with the parameter android:gravity from the TextView component, changed from "center_horizontal" to "center".



Let's continue modifying components options, because this way we will understand better the behavior of each parameter. Below there is the resulting layout when we modify the parameters android:layout_width and android:layout_height to "match_parent" to "wrap_content".



Thus, the size of the FrameLayout became the same size as the TextView. Hard to understand? So let's give the TextView a color:



The result is shown below.



Now it's easy to understand that the FrameLayout size of became the same size of the TextView. Now, if we change the parameters android:layout_width and android:layout_height of the FrameLayout from "wrap_content" to "match_parent" (which is the original value, displayed in the 1st picture of this topic), we have the following result.



So, in the previous example, the size of FrameLayout had become the same size of the TextView, through the use of "wrap_content". Now, the size of the FrameLayout became the size of the mobile phone screen, by using the "match_parent" option. Understanding these concepts of screen size expandable options is INDISPENSABLE to develop any layout in Android. It's extremely important to understand these concepts, otherwise the creation of layout's in Android will become much more complicated.

Continuing FrameLayout explanation, is shown below the XML from above with some more options in order to make the text appear more elegant.



The result of this new XML is shown below:



In this new XML, we changed the background color of the FrameLayout from black (default color) to blue, through the parameter android:background with the value "#2244AA", that is a soft blue. But why the majority of the screen is in white color? Because that's the color of the TextView (through option android:background="#FFFFFF"). As the size screen parameters from the FrameLayout and TextView are "match_parent", the screen size is the size of the TextView. However, we have a new parameter in FrameLayout: android:padding="5dp". What is this parameter? With this parameter, you create an inner margin between the FrameLayout and the TextView, with size of 5dp. The term "dp" can be understood here.

Thus, as the color of the FrameLayout is blue, and from the TextView is white, we have a contrast on the screen, giving the impression that a border was created.

Following the explanation, we have the options android:textsize (text size), android:textstyle (text style, which is bold in this case), and android:textColor (text color, which is red in this case).

Now we will talk about other types of layout.

LinearLayout
In FrameLayout we have only one child component. But in LinearLayout, we have several. This layout is designed for cases like several structures on the screen in a linear way. In this layout we have a parameter that don't exist in FrameLayout: android:orientation. It can have "vertical" or "horizontal" options. To demonstrate it's operation, we will use another XML, shown below.



Now we have more than one component on the screen. The result of the above XML is shown below.



So, we have 2 TextView's, one under the other, in vertical orientation. Since both TextView has the parameters android:layout_width="match_parent" and android:layout_height="wrap_content", we have the width with a maximum length and the height with minimum size (the size of the TextView). Below is the inversion of those values​​, where the orientation of the LinearLayout is horizontal.



Here is the result of this new XML:



As the TextView's were very close, we can give a spacing between them. This is shown in the following XML:



Here is the result:



What was added was now the parameter android:layout_margin="5dp". It created an outside edge (do not confuse with padding, which is an inset) between the 2 TextView's. But still, the texts are too "stuck" in TextView. So now, we will use the padding to give an internal spacing in their writing.



Here is the result:



To end this basic explanation about LinearLayout's, we will speak about the parameter layout_weight. Below we have a new XML.



In it, we have included a new TextView, and modified the orientation of the LinearLayout from horizontal to vertical. However, we included the parameter android:layout_weight="1". This parameter gives priority to the size of the TextView where it is set (in this case, the 1st TextView). In other words, it boosts the size of the width/height of this component, overwriting the effectiveness (making useful operation) of the parameter android:layout_width and android:layout_height. Thus, it "extends" the size of this TextView to where the screen size leave. The result can be seen below:



And now, the result when we set android:layout_weight="1" also in the 2nd TextView.



And also in 3rd.



So, the parameter layout_weight gives "weight" for each component. As in the previous image all components have same weight, they occupy the same place on the screen. However, this parameter overrides the functionality of parameters android:layout_width and android:layout_height. To finish layout_weight explanation, what happens when we set all TextView as android:layout_weight="1", but the 1st TextView as android:layout_weight="2"?



That is what happends. It balanced the weight of components according to the value of the parameters android:layout_weight of each TextView.

Now, we will learn a bit about TableLayout.

TableLayout
This layout is commonly used when we need listing various components in the same row, along a same screen. For example, create a layout with 18 TextView's split 3-3 along 6 lines. To create a layout like that, we could use 6 LinearLayout's, but it would spend much source code in XML, plus lots of memory on Android. The solution for this case would be using a TableLayout.

If we wanna have certain components used in only one line of TableLayout, the component used is TableRow. Below is an example of it's use:



And the result of this XML:



With the above example, we can deduce what effect one TableLayout has. If the component TableRow wouldn't be used, the TableLayout would become a LinearLayout.

To better understand the functioning of TableLayout, we will practice an exercise. We will create a layout with 6 lines, each containing 3 TextView's of equal size. The result will be the layout below.



Well, we can now realize that the generated XML source code will be huge (passing 250 lines for both cases), because we have to replicate enough code to create those 18's TextView. One tip to avoid this re-typing job is to create a style for our TextView. To create a style, we must create an XML file in the folder res/values​​, called styles.xml. In this file, we will create the generic layout of our TextView's. Below is shown how would be the syntax of this file.



Now we need to put this new style in our XML. So, we would have as result an XML file with only 110 lines, more than half the size of lines of XML without using styles.



-----

With these 3 types of layout we can create a tremendous amount of layout in Android. There are other types of layout (and other visual components) that will be seen on the blog in the next posts.

If someone has a question, suggestion or criticism, feel at ease.