blob: 30ae0ae32be29c2e8a6fedc644c63ac8308dc1a3 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.newsreader;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.SpinnerAdapter;
/**
* Main activity: shows headlines list and articles, if layout permits.
*
* This is the main activity of the application. It can have several different layouts depending
* on the SDK version, screen size and orientation. The configurations are divided in two large
* groups: single-pane layouts and dual-pane layouts.
*
* In single-pane mode, this activity shows a list of headlines using a {@link HeadlinesFragment}.
* When the user clicks on a headline, a separate activity (a {@link ArticleActivity}) is launched
* to show the news article.
*
* In dual-pane mode, this activity shows a {@HeadlinesFragment} on the left side and an
* {@ArticleFragment} on the right side. When the user selects a headline on the left, the
* corresponding article is shown on the right.
*
* If an Action Bar is available (large enough screen and SDK version 11 or up), navigation
* controls are shown in the Action Bar (whether to show tabs or a list depends on the layout).
* If an Action Bar is not available, a regular image and button are shown in the top area of
* the screen, emulating an Action Bar.
*/
public class NewsReaderActivity extends FragmentActivity
implements HeadlinesFragment.OnHeadlineSelectedListener,
CompatActionBarNavListener,
OnClickListener {
// Whether or not we are in dual-pane mode
boolean mIsDualPane = false;
// The fragment where the headlines are displayed
HeadlinesFragment mHeadlinesFragment;
// The fragment where the article is displayed (null if absent)
ArticleFragment mArticleFragment;
// The news category and article index currently being displayed
int mCatIndex = 0;
int mArtIndex = 0;
NewsCategory mCurrentCat;
// List of category titles
final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
// find our fragments
mHeadlinesFragment = (HeadlinesFragment) getSupportFragmentManager().findFragmentById(
R.id.headlines);
mArticleFragment = (ArticleFragment) getSupportFragmentManager().findFragmentById(
R.id.article);
// Determine whether we are in single-pane or dual-pane mode by testing the visibility
// of the article view.
View articleView = findViewById(R.id.article);
mIsDualPane = articleView != null && articleView.getVisibility() == View.VISIBLE;
// Register ourselves as the listener for the headlines fragment events.
mHeadlinesFragment.setOnHeadlineSelectedListener(this);
// Set up the Action Bar (or not, if one is not available)
int catIndex = savedInstanceState == null ? 0 : savedInstanceState.getInt("catIndex", 0);
setUpActionBar(mIsDualPane, catIndex);
// Set up headlines fragment
mHeadlinesFragment.setSelectable(mIsDualPane);
restoreSelection(savedInstanceState);
// Set up the category button (shown if an Action Bar is not available)
Button catButton = (Button) findViewById(R.id.categorybutton);
if (catButton != null) {
catButton.setOnClickListener(this);
}
}
/** Restore category/article selection from saved state. */
void restoreSelection(Bundle savedInstanceState) {
if (savedInstanceState != null) {
setNewsCategory(savedInstanceState.getInt("catIndex", 0));
if (mIsDualPane) {
int artIndex = savedInstanceState.getInt("artIndex", 0);
mHeadlinesFragment.setSelection(artIndex);
onHeadlineSelected(artIndex);
}
}
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
restoreSelection(savedInstanceState);
}
/** Sets up Action Bar (if present).
*
* @param showTabs whether to show tabs (if false, will show list).
* @param selTab the selected tab or list item.
*/
public void setUpActionBar(boolean showTabs, int selTab) {
if (Build.VERSION.SDK_INT < 11) {
// No action bar for you!
// But do not despair. In this case the layout includes a bar across the
// top that looks and feels like an action bar, but is made up of regular views.
return;
}
android.app.ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(false);
// Set up a CompatActionBarNavHandler to deliver us the Action Bar nagivation events
CompatActionBarNavHandler handler = new CompatActionBarNavHandler(this);
if (showTabs) {
actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
int i;
for (i = 0; i < CATEGORIES.length; i++) {
actionBar.addTab(actionBar.newTab().setText(CATEGORIES[i]).setTabListener(handler));
}
actionBar.setSelectedNavigationItem(selTab);
}
else {
actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
SpinnerAdapter adap = new ArrayAdapter<String>(this, R.layout.actionbar_list_item,
CATEGORIES);
actionBar.setListNavigationCallbacks(adap, handler);
}
// Show logo instead of icon+title.
actionBar.setDisplayUseLogoEnabled(true);
}
@Override
public void onStart() {
super.onStart();
setNewsCategory(0);
}
/** Sets the displayed news category.
*
* This causes the headlines fragment to be repopulated with the appropriate headlines.
*/
void setNewsCategory(int categoryIndex) {
mCatIndex = categoryIndex;
mCurrentCat = NewsSource.getInstance().getCategory(categoryIndex);
mHeadlinesFragment.loadCategory(categoryIndex);
// If we are displaying the article on the right, we have to update that too
if (mIsDualPane) {
mArticleFragment.displayArticle(mCurrentCat.getArticle(0));
}
// If we are displaying a "category" button (on the ActionBar-less UI), we have to update
// its text to reflect the current category.
Button catButton = (Button) findViewById(R.id.categorybutton);
if (catButton != null) {
catButton.setText(CATEGORIES[mCatIndex]);
}
}
/** Called when a headline is selected.
*
* This is called by the HeadlinesFragment (via its listener interface) to notify us that a
* headline was selected in the Action Bar. The way we react depends on whether we are in
* single or dual-pane mode. In single-pane mode, we launch a new activity to display the
* selected article; in dual-pane mode we simply display it on the article fragment.
*
* @param index the index of the selected headline.
*/
@Override
public void onHeadlineSelected(int index) {
mArtIndex = index;
if (mIsDualPane) {
// display it on the article fragment
mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
}
else {
// use separate activity
Intent i = new Intent(this, ArticleActivity.class);
i.putExtra("catIndex", mCatIndex);
i.putExtra("artIndex", index);
startActivity(i);
}
}
/** Called when a news category is selected.
*
* This is called by our CompatActionBarNavHandler in response to the user selecting a
* news category in the Action Bar. We react by loading and displaying the headlines for
* that category.
*
* @param catIndex the index of the selected news category.
*/
@Override
public void onCategorySelected(int catIndex) {
setNewsCategory(catIndex);
}
/** Save instance state. Saves current category/article index. */
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("catIndex", mCatIndex);
outState.putInt("artIndex", mArtIndex);
super.onSaveInstanceState(outState);
}
/** Called when news category button is clicked.
*
* This is the button that we display on UIs that don't have an action bar. This button
* calls up a list of news categories and switches to the given category.
*/
@Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select a Category");
builder.setItems(CATEGORIES, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setNewsCategory(which);
}
});
AlertDialog d = builder.create();
d.show();
}
}