User Tools

Site Tools


android_learning:headfirst_android_development_notes:chapter_10

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
android_learning:headfirst_android_development_notes:chapter_10 [2016/03/16 03:29] – [Foreword] mithatandroid_learning:headfirst_android_development_notes:chapter_10 [2016/03/16 04:49] (current) – [Foreword] mithat
Line 1: Line 1:
 ====== Chapter 10 ====== ====== Chapter 10 ======
  
-<WRAP center round info 60%> +===== Foreword ===== 
-Under development. +I think Android's action bars, action items, and navigation drawers are implemented pretty terribly---the last of these being especially painful to write code for. The backstack for Fragments isn't much better. It's as though thousands of years of desktop app development framework development never happened
-</WRAP>+ 
 +If you get frustrated in this chapter, I feel your pain. It's not you, it's Android. If there's good news, it's that Android Studio's "Blank" activity template sets up some of necessary scaffolding and boilerplate code for you. But you still need to know the inner workings. So ...
  
-===== Foreword ===== +===== p. 398: Creating the app ===== 
-I think Android's action bars, action items, and navigation drawers are implemented pretty terribly---the last of these being especially painful. It's as though thousands of years of desktop app development framework development never existed. If you get frustrated in this chapterI feel your pain. It's not you, it's Android+ 
 +If you are creating a new app from scratch rather than expanding on what you build for Chapter 9be sure you specify an **Empty app template** in the new app wizard.
 ===== p 401: "Fragment name is not a valid class name" ===== ===== p 401: "Fragment name is not a valid class name" =====
 There is a subtlety in creating new Android fragments in Android Studio that Android Studio does a horrible job of negotiating. There is a subtlety in creating new Android fragments in Android Studio that Android Studio does a horrible job of negotiating.
Line 25: Line 27:
 ===== p 401: Project dependencies ===== ===== p 401: Project dependencies =====
  
-In the preceding chapter, you were instructed to remove the project's dependency on ''com.android.support:appcompat-v7:<whatever>'' and/or ''com.android.support:appcompat-v4:<whatever>'' to work around an Android Studio bug. However, the DrawerLayout that we will use in a bit //requires// the v4 compat libs. +In the preceding chapter, you were instructed to remove the project's dependency on ''com.android.support:appcompat-v7:<whatever>'' and/or ''com.android.support:appcompat-v4:<whatever>'' to work around an Android Studio bug. However, the DrawerLayout that is the main subject of this chapter //requires// the v4 compat libs. 
  
 {{ https://upload.wikimedia.org/wikipedia/commons/3/3b/Paris_Tuileries_Garden_Facepalm_statue.jpg?300 }} {{ https://upload.wikimedia.org/wikipedia/commons/3/3b/Paris_Tuileries_Garden_Facepalm_statue.jpg?300 }}
  
-<WRAP center round important 90%> +So, leave ''com.android.support:appcompat-v7'' as a project dependency or add it back if you removed it---and hope the Android Studio bugs stay in their holes. A dependence on ''com.android.support:appcompat-v7'' will automatically bring in ''v4''.
-Leave ''com.android.support:appcompat-v7:<whatever>'' as a project dependency or add it back if you removed it. +
-</WRAP> +
- +
-A dependence on ''com.android.support:appcompat-v7:<whatever>'' will automatically bring in ''v4''.+
  
 ===== p 401: Code blocks ===== ===== p 401: Code blocks =====
Line 69: Line 67:
 </file> </file>
  
-Notice the required empty public constructor not included in the book's code.+Notice the required empty public constructor not included in the book's code. The [[http://developer.android.com/reference/android/app/Fragment.html|official docs]] assert that:
  
-<WRAP center round info 90%> +> All subclasses of Fragment must include a public no-argument constructor.
-The [[http://developer.android.com/reference/android/app/Fragment.html|official docs say]] "All subclasses of Fragment must include a public no-argument constructor." The book doesn't follow this practice, but you should. +
-</WRAP>+
  
 +The book doesn't follow this practice, but you should.
  
 And here's the layout: And here's the layout:
Line 226: Line 223:
  
 ===== p. 417: Anonymous classes ===== ===== p. 417: Anonymous classes =====
-In case you're not familiar with the construct of the ''ActionBarDrawerToggle'' definition code, it's using Java's anonymous inner class syntax. Anonymous inner classes are typically used as shortcuts to creating a derived class that you'll only use once.+In case you're not familiar with how the ''ActionBarDrawerToggle'' here is being defined, it's using Java's anonymous inner class syntax. Anonymous inner classes are typically used as shortcuts to creating a derived class that you'll only use once.
  
 ===== p. 422: Code block ===== ===== p. 422: Code block =====
Line 414: Line 411:
 </file> </file>
  
 +===== pp. 429-434 =====
 +I think the length of the ActivityMain class definition is an indication of how poorly designed the Android features introduced in this and the previous chapter are. But you be the judge.
  
 +Note when you add code that references the FragmentManager class to your code, you'll be offered two different class options to import. Use ''android.app.FragmentManager''.
 +
 +<file java ActivityMain.java>
 +package com.hfad.bitsandpizzas;
 +
 +import android.app.Activity;
 +import android.app.Fragment;
 +import android.app.FragmentManager;
 +import android.app.FragmentTransaction;
 +import android.content.Intent;
 +import android.content.res.Configuration;
 +import android.os.Bundle;
 +import android.support.v4.widget.DrawerLayout;
 +import android.support.v7.app.ActionBarDrawerToggle;
 +import android.view.Menu;
 +import android.view.MenuItem;
 +import android.view.View;
 +import android.widget.AdapterView;
 +import android.widget.ArrayAdapter;
 +import android.widget.ListView;
 +import android.widget.ShareActionProvider;
 +import android.widget.Toast;
 +
 +public class MainActivity extends Activity {
 +
 +    private ShareActionProvider shareActionProvider;
 +    private String[] titles;        // local list of categories
 +    private ListView drawerList;
 +    private DrawerLayout drawerLayout;
 +    private ActionBarDrawerToggle drawerToggle;
 +    private int currentPosition = 0;
 +
 +    private class DrawerItemClickListener implements ListView.OnItemClickListener {
 +
 +        @Override
 +        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 +            selectItem(position);
 +        }
 +    }
 +
 +    @Override
 +    protected void onCreate(Bundle savedInstanceState) {
 +        super.onCreate(savedInstanceState);
 +        setContentView(R.layout.activity_main);
 +
 +        // populate local list of categories
 +        titles = getResources().getStringArray(R.array.titles);
 +        drawerList = (ListView) findViewById(R.id.drawer);
 +        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
 +
 +        // Populate the list view
 +        drawerList.setAdapter(new ArrayAdapter<String>(this,
 +                android.R.layout.simple_list_item_activated_1, titles));
 +        drawerList.setOnItemClickListener(new DrawerItemClickListener());
 +
 +        // Display the correct fragment
 +        if (savedInstanceState != null) {
 +            currentPosition = savedInstanceState.getInt("position");
 +            setActionBarTitle(currentPosition);
 +        } else {  // if MainActivity newly created ...
 +            selectItem(0);
 +        }
 +
 +        // Create the ActionBarToggle ...
 +        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
 +                R.string.open_drawer, R.string.close_drawer) {
 +
 +            @Override
 +            public void onDrawerClosed(View drawerView) {
 +                super.onDrawerClosed(drawerView);
 +                invalidateOptionsMenu();
 +            }
 +
 +            @Override
 +            public void onDrawerOpened(View drawerView) {
 +                super.onDrawerOpened(drawerView);
 +                invalidateOptionsMenu();
 +            }
 +        };
 +        // ... and set the ActionBarToggle as the drawer's listener
 +        drawerLayout.setDrawerListener(drawerToggle);
 +
 +        getActionBar().setDisplayHomeAsUpEnabled(true);
 +        getActionBar().setHomeButtonEnabled(true);
 +
 +        // Add a listener for changes in the backstack to the fragment manager,
 +        // use that to set titles appropriately and check drawer items.
 +        getFragmentManager().addOnBackStackChangedListener(
 +                new FragmentManager.OnBackStackChangedListener() {
 +
 +                    @Override
 +                    public void onBackStackChanged() {
 +                        FragmentManager fragMan = getFragmentManager();
 +                        Fragment fragment = fragMan.findFragmentByTag("visible_fragment");
 +
 +                        if (fragment instanceof TopFragment) {
 +                            currentPosition = 0;
 +                        }
 +                        if (fragment instanceof PizzaFragment) {
 +                            currentPosition = 1;
 +                        }
 +                        if (fragment instanceof PastaFragment) {
 +                            currentPosition = 2;
 +                        }
 +                        if (fragment instanceof StoresFragment) {
 +                            currentPosition = 3;
 +                        }
 +                        setActionBarTitle(currentPosition);
 +                        drawerList.setItemChecked(currentPosition, true);
 +                    }
 +
 +                }
 +        );
 +    }
 +
 +    @Override
 +    protected void onSaveInstanceState(Bundle outState) {
 +        super.onSaveInstanceState(outState);
 +        outState.putInt("position", currentPosition);
 +    }
 +
 +    @Override
 +    protected void onPostCreate(Bundle savedInstanceState) {
 +        super.onPostCreate(savedInstanceState);
 +        // sync toggle state (after onRestoreInstanceState has occurred).
 +        drawerToggle.syncState();
 +    }
 +
 +    @Override
 +    public void onConfigurationChanged(Configuration newConfig) {
 +        super.onConfigurationChanged(newConfig);
 +        drawerToggle.onConfigurationChanged(newConfig);
 +    }
 +
 +    @Override
 +    public boolean onPrepareOptionsMenu(Menu menu) {
 +        // If the drawer is open, hide action items related to the content view.
 +        boolean drawerOpen = drawerLayout.isDrawerOpen(drawerList);
 +        menu.findItem(R.id.action_share).setVisible(!drawerOpen);
 +        return super.onPrepareOptionsMenu(menu);
 +    }
 +
 +    private void selectItem(int position) {
 +        currentPosition = position;
 +        // update the main content by replacing fragments
 +        Fragment fragment;
 +        switch (position) {
 +            case 1:
 +                fragment = new PizzaFragment();
 +                break;
 +            case 2:
 +                fragment = new PastaFragment();
 +                break;
 +            case 3:
 +                fragment = new StoresFragment();
 +                break;
 +            default:
 +                fragment = new TopFragment();
 +        }
 +        FragmentTransaction ft = getFragmentManager().beginTransaction();
 +        ft.replace(R.id.content_frame, fragment, "visible_fragment")
 +                .addToBackStack(null)
 +                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
 +                .commit();
 +
 +        //Set the action bar title
 +        setActionBarTitle(position);
 +
 +        //Close drawer
 +        drawerLayout.closeDrawer(drawerList);
 +    }
 +
 +    private void setActionBarTitle(int position) {
 +        String title;
 +
 +        if (position == 0) {
 +            title = getResources().getString(R.string.app_name);
 +        } else {
 +            title = titles[position];
 +        }
 +        getActionBar().setTitle(title);
 +    }
 +
 +    @Override
 +    public boolean onCreateOptionsMenu(Menu menu) {
 +        // Add menu_main items to the action bar (if present):
 +        getMenuInflater().inflate(R.menu.menu_main, menu);
 +        MenuItem menuItem = menu.findItem(R.id.action_share);
 +        shareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
 +        setIntent("This is example text.");
 +        return super.onCreateOptionsMenu(menu);
 +    }
 +
 +    @Override
 +    public boolean onOptionsItemSelected(MenuItem item) {
 +        // If a drawer option has been clicked ...
 +        if (drawerToggle.onOptionsItemSelected(item)) {
 +            // do nothing and return.
 +            return true;
 +        }
 +
 +        // ... otherwise ...
 +        switch (item.getItemId()) {
 +            case R.id.action_create_order:
 +                //Code to run when the Create Order item is clicked
 +                Intent intent = new Intent(this, OrderActivity.class);
 +                startActivity(intent);
 +                return true;
 +            case R.id.action_settings:
 +                //Code to run when the settings item is clicked
 +                Toast.makeText(MainActivity.this, "Settings!", Toast.LENGTH_SHORT).show();
 +                return true;
 +            default:
 +                return super.onOptionsItemSelected(item);
 +        }
 +    }
 +
 +    private void setIntent(String text) {
 +        Intent intent = new Intent(Intent.ACTION_SEND);
 +        intent.setType("text/plain");
 +        intent.putExtra(Intent.EXTRA_TEXT, text);
 +        shareActionProvider.setShareIntent(intent);
 +    }
 +}
 +</file>
android_learning/headfirst_android_development_notes/chapter_10.1458098983.txt.gz · Last modified: 2016/03/16 03:29 by mithat

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki