720 likes | 861 Views
Mobile Programming Lecture 5. Composite Views, Activities, Intents and Filters. Lecture 4 Review. How do you get the value of a string in the strings.xml file? What are the steps to populate a Spinner or ListView using XML? How many Android application components are there? Name one.
E N D
Mobile Programming Lecture 5 Composite Views, Activities, Intents and Filters
Lecture 4 Review • How do you get the value of a string in the strings.xml file? • What are the steps to populate a Spinner or ListView using XML? • How many Android application components are there? Name one. • How do you launch an Activity B from within Activity A?
Agenda • ViewFlipper • SlidingDrawer • TabLayout • Activity LifeCycle • Configuration Changes • URI • Intent Filters
ViewFlipper A ViewFlipper allows you to switch between views that are children of the ViewFlipper You can find it in the Transitions menu in Graphical Layout
ViewFlipper <ViewFlipper android:id="@+id/myViewFlipper" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > </RelativeLayout> </ViewFlipper>
ViewFlipper <ViewFlipper android:id="@+id/myViewFlipper" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > </RelativeLayout> </ViewFlipper> Here I used RelativeLayouts, but you can place any widget you want in here.
ViewFlipper <ViewFlipper android:id="@+id/myViewFlipper" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="match_parent" android:layout_height=“wrap_content" /> <TextView android:layout_width="match_parent" android:layout_height=“match_parent“ / > </ViewFlipper> Here I also used just 2 Views. You can add more than just 2 Views if you want to.
ViewFlipper ViewFlipper flipper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); flipper = (ViewFlipper) findViewById(R.id.viewFlipper1); flipper.setFlipInterval(500); flipper.startFlipping(); }
ViewFlipper ViewFlipper flipper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); flipper = (ViewFlipper) findViewById(R.id.viewFlipper1); flipper.setFlipInterval(500); flipper.startFlipping(); } Here we set the flipper to flip every 500 milliseconds
ViewFlipper ViewFlipper flipper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); flipper.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { flipper.showNext(); } }); } Here we set the flipper to flip when the flipper is clicked
FrameLayout • FrameLayout is designed to block out an area on the screen to display a single item. • FrameLayout should be used to hold a single child view • it can be difficult to organize child views in a way that's scalable to different screen sizes without the children overlapping each other
FrameLayout • Example:
SlidingDrawer • hides content out of the screen and allows the user to drag a handle to bring the content on screen • can be used vertically or horizontally • composed of two children views • the handle, that the users drags • the content, attached to the handle and dragged with it. • should only be used inside of a FrameLayout or a RelativeLayout
SlidingDrawer • Note:the android:handle and android:content attributes • There needs to be children with id's matching these attributes
SlidingDrawer - useful attributes • android:handle • android:content • android:orientation • "vertical" or "horizontal" • android:allowSingleTap • "true" or "false" • allow the user to open the drawer by tapping on the handle?
SlidingDrawer - useful methods • open() • close() • setOnDrawerScrollListener(OnDrawerScrollListener) • setOnDrawOpenListener(OnDrawerOpenListener) • setOnDrawerCloseListener(OnDrawerCloseListener)
TabLayout It is used to wrap multiple activities into a single window • navigate through the activities using tabs
TabLayout - Anatomy • TabHost • container holding TabWidget and a FrameLayout • TabWidget • row of tab buttons • FrameLayout • container holding the tab contents • each tab content is a child of FrameLayout ACTIVITY TABHOST TABWIDGET FRAMELAYOUT TAB CONTENT
TabLayout - XML <?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> </TabHost> ACTIVITY TABHOST TABWIDGET FRAMELAYOUT TAB CONTENT
TabLayout - XML <?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> </TabHost> ACTIVITY TABHOST TABWIDGET FRAMELAYOUT TAB CONTENT Tabs are different Activities, we can set and specify the layout for each tab programmatically
TabLayout If you're going to have x number of tabs, create x number of Activities, 1 for each tab, in addition to the TabActivity (Host Activity). You can create x number of XML layouts for each tab, or you can reuse the same layout for each tab.
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); // The activity TabHost TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); }
TabLayout extend TabActivity public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); // The activity TabHost TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); }
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); // The activity TabHost TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } the XML file containing the TabHost, TabWidget, FrameLayout
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Reference to the Activity's TabHost (which was defined in XML)
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Reusable TabSpec for each Tab.
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } The TabSpec tells the TabHost what views represent the tab contents and what the tab buttons should look like.
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Remember from the previous lecture, this is how we use an Intent object to start another Activity
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Refer to this TabActivity's tab host (which will contain the actual tabs)
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Create a new tab spec, give it the id "linear layout"
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Set the label for the tab (label the user sees) to "Linear". And
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } We're not using an image for the tabs, so null for this argument
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Fill the FrameLayout to hold the Activity specified by this intent
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } Add the tab to the tabHost, it will now show up in the UI
TabLayout public class TabLayoutExampleActivity extends TabActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TabHost tabHost = getTabHost(); TabHost.TabSpec spec; Intent intent = new Intent(TabLayoutExampleActivity.this, LinearLayout.class); spec = tabHost.newTabSpec("linear layout").setIndicator("Linear", null).setContent(intent); tabHost.addTab(spec); Intent intent = new Intent(TabLayoutExampleActivity.this, TableLayout.class); spec = tabHost.newTabSpec("table layout").setIndicator("Table",null).setContent(intent); tabHost.addTab(spec); } To add another tab, let's do this all over again!
TabLayout - Rules • TabHost must have the id@android:id/tabhost • The TabWidget must have the id @android:id/tabs • The FrameLayout must have the id @android:id/tabcontent
TabHost - useful methods • setCurrentTab(int) • make this tab the active tab, making it visible in the UI • setOnTabChangedListener(OnTabChangedListener) • react to when the active tab changes
Activity LifeCycle • During the life of an activity, the system calls a core set of lifecycle methods in a sequence. • Implementing your activity lifecycle methods properly ensures your app behaves gracefully in many ways, including that it: • Does not crash if the user receives a phone call or switches to another app while using your app. • Does not consume valuable system resources when the user is not actively using it. • Does not lose the user's progress if they leave your app and return to it at a later time.
Activity Lifecycle A nice picture of activity lifecycle http://developer.android.com/reference/android/app/Activity.html
Activity LifeCycle - onCreate() • Called when the activity is first created. • this is where you should do all of your normal static set up: create views, bind data to lists, etc. • provides you with a Bundle containing the activity's previously frozen state, if there was one. • always followed by onStart().
Activity LifeCycle - onStart() • called when the activity is becoming visible to the user • followed by • onResume() if the activity comes to the foreground
Activity LifeCycle - onRestart() • called after your activity has been stopped, prior to it being started again • always followed by onStart()
Activity LifeCycle - onResume() • called when the activity will start interacting with the user • at this point your activity is at the top of the activity stack, with user input going to it • Always followed by onPause()
Activity LifeCycle - onPause() • called when the system is about to start resuming a previous activity • this is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc • implementations of this method must be very quick because the next activity will not be resumed until this method returns • followed by • onResume() if the activity returns back to the front • onStop() if it becomes invisible to the user.
Activity LifeCycle - onStop() • called when the activity is no longer visible to the user because another activity has been resumed and is covering this one • this may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed • followed by • onRestart() if this activity is coming back to interact with the user • onDestroy() if this activity is going away
Activity LifeCycle - onDestroy() • the final call you receive before your activity is destroyed • this can happen either because • the activity is finishing (someone called finish()) • the system is temporarily destroying this instance of the activity due to low memory • you can distinguish between these two scenarios with the isFinishing() method
Reading Assignment Please read page 0 – 710 by next class. Pay more attention on the section of Large-Screen Strategies and Tactics. We are going to talk about Fragment next week.
Configuration Changes • In your app, you can detect when the configuration of the device changes • screen orientation, keyboard availability, and language • In default, the system will try to handle the changes for you, unless you specify that you want to handle them yourself
Configuration Changes - Manifest • to specify that, you want to handle orientation and keyboard availability changes by yourself • open the manifest file and add the bold line <activity android:configChanges="orientation|keyboardHidden" android:name=".OnConfigurationChangedExampleActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Configuration Changes - Manifest • This specifies one or more configuration changes that the activity will handle itself when the orientation changes and when keyboard availability changes. <activity android:configChanges="orientation|keyboardHidden" android:name=".OnConfigurationChangedExampleActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>