响应这一事件的方式和返回主活动的方式是相同的(和上文所说的类似,只不过现在是根据当前的活动是哪一个来启动另一个不同的活动)。为了告诉用户这时的情况将有所不同,唯一需要做的就是把Action Bar设为“show home as up”。这通过对活动的ActionBar调用setDisplayHomeAsUpEnabled(true)即可完成。这时,系统将为应用程序的图标增加一个表示向上一层动作的箭头,就像图4这样。
private classMyTabListenerimplementsActionBar.TabListener { private TabContentFragment mFragment; // Called to create an instance of the listener when adding a new tab publicMyTabListener(TabContentFragment fragment) { mFragment = fragment; } public void onTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment_content, mFragment, null); } public void onTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(mFragment); } public void onTabReselected(Tab tab, FragmentTransaction ft) { // do nothing }}
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // setup Action Bar for tabs finalActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // remove the activity title to make space for tabs actionBar.setDisplayShowTitleEnabled(false); // instantiate fragment for the tab Fragment artistsFragment = newArtistsFragment(); // add a new tab and set its title text and tab listener actionBar.addTab(actionBar.newTab().setText(R.string.tab_artists) .setTabListener(newTabListener(artistsFragment))); Fragment albumsFragment = newAlbumsFragment(); actionBar.addTab(actionBar.newTab().setText(R.string.tab_albums) .setTabListener(newTabListener(albumsFragment)));}
public static classFragmentAextendsListFragment { ... // Container Activity must implement this interface public interfaceOnArticleSelectedListener { public void onArticleSelected(Uri articleUri); } ...}
public static classFragmentAextendsListFragment { OnArticleSelectedListener mListener; ... @Override public void onListItemClick(ListView l, View v, int position, long id) { // Append the clicked item's row ID with the content provider Uri Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id); // Send the event and Uri to the host activity mListener.onArticleSelected(noteUri); } ...}
public staticclassTitlesFragmentextendsListFragment { boolean mDualPane; int mCurCheckPosition = 0; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Populate list with our static array of titles. setListAdapter(newArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES)); // Check to see if we have a frame in which to embed the details // fragment directly in the containing UI. View detailsFrame = getActivity().findViewById(R.id.details); mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; if (savedInstanceState != null) { // Restore last state for checked position. mCurCheckPosition = savedInstanceState.getInt("curChoice", 0); } if (mDualPane) { // In dual-pane mode, the list view highlights the selected item. getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); // Make sure our UI is in the correct state. showDetails(mCurCheckPosition); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("curChoice", mCurCheckPosition); } @Override public void onListItemClick(ListView l, View v, int position, long id) { showDetails(position); } /** * Helper function to show the details of a selected item, either by * displaying a fragment in-place in the current UI, or starting a * whole new activity in which it is displayed. */ void showDetails(int index) { mCurCheckPosition = index; if (mDualPane) { // We can display everything in-place with fragments, so update // the list to highlight the selected item and show the data. getListView().setItemChecked(index, true); // Check what fragment is currently shown, replace if needed. DetailsFragment details = (DetailsFragment) getFragmentManager().findFragmentById(R.id.details); if (details == null || details.getShownIndex() != index) { // Make new fragment to show this selection. details = DetailsFragment.newInstance(index); // Execute a transaction, replacing any existing fragment // with this one inside the frame. FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.details, details); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); ft.commit(); } } else { // Otherwise we need to launch a new activity to display // the dialog fragment with selected text. Intent intent = newIntent(); intent.setClass(getActivity(), DetailsActivity.class); intent.putExtra("index", index); startActivity(intent); } }}
public static classDetailsFragmentextendsFragment { /** * Create a new instance of DetailsFragment, initialized to * show the text at 'index'. */ public staticDetailsFragment newInstance(int index) { DetailsFragment f = newDetailsFragment(); // Supply index input as an argument. Bundle args = new Bundle(); args.putInt("index", index); f.setArguments(args); return f; } public int getShownIndex() { return getArguments().getInt("index", 0); } @Override publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (container == null) { // We have different layouts, and in one of them this // fragment's containing frame doesn't exist. The fragment // may still be created from its saved state, but there is // no reason to try to create its view hierarchy because it // won't be displayed. Note this is not needed -- we could // just run the code below, where we would create and return // the view hierarchy; it would just never be used. return null; } ScrollView scroller = newScrollView(getActivity()); TextView text = newTextView(getActivity()); int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getActivity().getResources().getDisplayMetrics()); text.setPadding(padding, padding, padding, padding); scroller.addView(text); text.setText(Shakespeare.DIALOGUE[getShownIndex()]); return scroller; }}
public static classDetailsActivityextendsActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { // If the screen is now in landscape mode, we can show the // dialog in-line with the list so we don't need this activity. finish(); return; } if (savedInstanceState == null) { // During initial setup, plug in the details fragment. DetailsFragment details = newDetailsFragment(); details.setArguments(getIntent().getExtras()); getFragmentManager().beginTransaction().add(android.R.id.content, details).commit(); } }}
<permissionGroup>属性是可选的,仅仅被用来帮助系统向用户显示该许可。通常会对一个标准系统组(standard system group)(列于android.Manifest.permission_group)或在某些特殊情况下对自己定义的系统组设置该属性。推荐使用一个已有的组,以简化向用户显示的许可界面。
<stringname="permlab_callPhone">directly call phone numbers</string> <stringname="permdesc_callPhone">Allows the application to call phone numbers without your intervention. Malicious applications may cause unexpected calls on your phone bill. Note that this does not allow the application to call emergency numbers.</string>
可以通过shell指令adb shell pm list permissions来查看当前系统中所定义的许可。一般来说,’-s’选项将会像展示给用户看到的那样展示这些许可。
$ adb shell pm list permissions -s All Permissions:Network communication: view Wi-Fi state, create Bluetooth connections, fullInternet access, view network stateYour location: access extra location provider commands, fine (GPS) location,mock location sources for testing, coarse (network-based) locationServices that cost you money: send SMS messages, directly call phone numbers...
// Get a Spinner and bind it to an ArrayAdapter that // references a String array.Spinner s1 = (Spinner) findViewById(R.id.spinner1);ArrayAdapter adapter = ArrayAdapter.createFromResource( this, R.array.colors, android.R.layout.simple_spinner_item);adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);s1.setAdapter(adapter);// Load a Spinner and bind it to a data query.private static String[] PROJECTION = new String[] { People._ID, People.NAME };Spinner s2 = (Spinner) findViewById(R.id.spinner2);Cursor cur = managedQuery(People.CONTENT_URI, PROJECTION, null, null);SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, // Use a template // that displays a // text view cur, // Give the cursor to the list adapter new String[] {People.NAME}, // Map the NAME column in the // people database to... new int[] {android.R.id.text1}); // The "text1" view defined in // the XML templateadapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);s2.setAdapter(adapter2);
// Create a message handling object as an anonymous class.private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Display a messagebox. Toast.makeText(mContext,"You've got an event",Toast.LENGTH_SHORT).show(); }};// Now hook into our object and set its onItemClickListener member// to our class handler object.mHistoryView = (ListView)findViewById(R.id.history);mHistoryView.setOnItemClickListener(mMessageClickedHandler);
当程序在响应用户交互操作中需要处理密集型工作时,这样的单线程模式可能会在没有很好的设计程序的情况下降低程序表现。特别是如果所有的任务都由UI线程执行,网络连接或是数据请求等长时间操作将会阻塞整个UI。当线程被阻塞,事件就无法被分发,包括绘图事件。从用户的角度来看,程序似乎就停止响应了。更糟糕的情况下,如果UI线程被阻塞的时间过长(目前来说大约是5秒)用户就会看到糟糕的“程序没有相应”(application not responding,ANR)对话框。用户之后就会考虑退出程序,甚至不满地卸载它。
public void onClick(View v) { new Thread(new Runnable() { public void run() { Bitmap b = loadImageFromNetwork("http://example.com/image.png"); mImageView.setImageBitmap(b); } }).start();}
public void onClick(View v) { new DownloadImageTask().execute("http://example.com/image.png");}private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { /** The system calls this to perform work in a worker thread and * delivers it the parameters given to AsyncTask.execute() */ protected Bitmap doInBackground(String... urls) { return loadImageFromNetwork(urls[0]); } /** The system calls this to perform work in the UI thread and delivers * the result from doInBackground() */ protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); }}