Back to project page BBC-News-Reader.
The source code is released under:
Copyright (c) 2011, 2012, Digital Lizard (Oscar Key, Thomas Boby) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the...
If you think the Android project BBC-News-Reader listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.digitallizard.bbcnewsreader.fragments; //from w ww.j ava 2s .com import java.util.ArrayList; import java.util.Arrays; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.actionbarsherlock.app.SherlockFragment; import com.digitallizard.bbcnewsreader.Item; import com.digitallizard.bbcnewsreader.ItemLayout; import com.digitallizard.bbcnewsreader.R; import com.digitallizard.bbcnewsreader.ReaderActivity; import com.digitallizard.bbcnewsreader.ResourceService; import com.digitallizard.bbcnewsreader.ServiceManager; import com.digitallizard.bbcnewsreader.ServiceManager.MessageReceiver; import com.digitallizard.bbcnewsreader.data.DatabaseHandler; public class FrontpageFragment extends SherlockFragment implements MessageReceiver { private static final int ITEM_MIN_WIDTH = 100; private static final int MAX_ITEMS_PER_ROW_PORTRAIT = 3; private static final int MAX_ITEMS_PER_ROW_LANDSCAPE = 5; private static final int MAX_ITEMS_PER_ROW_TABLET_LANDSCAPE = 5; private static final int PORTRAIT_CODE = 0; private static final float THUMB_HEIGHT_RATIO = 9/16f; private static final float FRAGMENT_SCREEN_RATIO = 3/5f; //FIXME this is not the right way to do this private DatabaseHandler database; private ServiceManager service; private FrontPageClickHandler clickHandler; private String[] categoryNames; private ArrayList<RelativeLayout> physicalCategories; private ItemLayout[][] physicalItems; private int categoryRowLength; // the number of items to show per row public interface FrontPageClickHandler { public void onItemClick(int id); public void onCategoryClick(String title); } public void handleMessage(Message msg) { switch (msg.what) { case ResourceService.MSG_FULL_LOAD_COMPLETE: loadUnloadedThumbs(); break; case ResourceService.MSG_CATEGORY_LOADED: categoryLoadFinished(msg.getData().getString(ResourceService.KEY_CATEGORY)); break; case ResourceService.MSG_THUMB_LOADED: updateItemThumb(msg.getData().getInt(ResourceService.KEY_ITEM_ID)); break; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // bind to the service service = new ServiceManager(getActivity(), this); service.doBindService(); // bind to the database database = new DatabaseHandler(this.getActivity()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.frontpage, container, false); createNewsDisplay(inflater, view); return view; } @Override public void onAttach(Activity activity) { super.onAttach(activity); // check that the parent has implemented the correct callbacks try { clickHandler = (FrontPageClickHandler) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement FrontPageClickHandlers"); } } @Override public void onDestroy() { super.onDestroy(); // unbind the service service.doUnbindService(); } public void createNewsDisplay(LayoutInflater inflater, View container) { //FIXME entire layout system needs fixing LinearLayout content = (LinearLayout) container.findViewById(R.id.newsScrollerContent); // a reference to the layout where we put the news // clear the content area content.removeAllViewsInLayout(); // find the width and work out how many items we can add and how wide they should be int rowPixelWidth = ((WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth(); // take into account screen orientation and device type int maxItemsPerRow = MAX_ITEMS_PER_ROW_PORTRAIT; if(((WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation() != PORTRAIT_CODE) { maxItemsPerRow = MAX_ITEMS_PER_ROW_LANDSCAPE; } //FIXME dangerous if(((ReaderActivity) getActivity()).getCurrentDisplayMode() == ReaderActivity.DISPLAY_MODE_TABLET_LANDSCAPE) { rowPixelWidth = (int) Math.floor(rowPixelWidth * FRAGMENT_SCREEN_RATIO); maxItemsPerRow = MAX_ITEMS_PER_ROW_TABLET_LANDSCAPE; } int rowWidth = (int) Math.floor(rowPixelWidth / this.getResources().getDisplayMetrics().density); // formula to convert from pixels to dp categoryRowLength = (int) Math.floor(rowWidth / ITEM_MIN_WIDTH); if (categoryRowLength > maxItemsPerRow) { categoryRowLength = maxItemsPerRow; } int thumbWidth = (int) Math.floor(rowPixelWidth / categoryRowLength); int thumbHeight = (int) Math.floor(((float) thumbWidth) * THUMB_HEIGHT_RATIO); // create the categories categoryNames = database.getEnabledCategories()[1]; // string array with category names in it physicalCategories = new ArrayList<RelativeLayout>(categoryNames.length); physicalItems = new ItemLayout[categoryNames.length][categoryRowLength]; // the array to hold the news items // loop through adding category views for (int i = 0; i < categoryNames.length; i++) { // create the category title bar RelativeLayout categoryTitleBar = (RelativeLayout) inflater.inflate(R.layout.list_category_item, null); // set a click listener categoryTitleBar.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { // FIXME there must be a more elegant way of doing this... // find the id of the category and report the click int id = physicalCategories.indexOf(view); clickHandler.onCategoryClick(categoryNames[id]); } }); // change the name TextView name = (TextView) categoryTitleBar.findViewById(R.id.categoryTitle); name.setText(categoryNames[i]); // store the category title bar and add it to the scroller physicalCategories.add(i, categoryTitleBar); // store the category for future use content.addView(categoryTitleBar); // create an item row and add items to it //TableRow itemRow = new TableRow(getActivity()); LinearLayout itemRow = new LinearLayout(getActivity()); for (int j = 0; j < categoryRowLength; j++) { // add a new item to the display ItemLayout item = (ItemLayout) inflater.inflate(R.layout.list_news_item, null); item.setPadding(1, 0, 1, 0); item.setImageSize(thumbWidth, thumbHeight); // set a click listener item.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { // retrieve the title of this activity ItemLayout item = (ItemLayout) view; // cast the view to a an itemlayout // check there is an item at this view if (item.isItem()) { // report the click clickHandler.onItemClick(item.getId()); } } }); physicalItems[i][j] = item; // store the item for future use itemRow.addView(item); // add the item to the display } // add the row to the display content.addView(itemRow); // populate this category with news displayCategoryItems(i); } } private void displayCategoryItems(int category) { // load from the database, if there's anything in it Item[] items = database.getItems(categoryNames[category], categoryRowLength); if (items != null) { // change the physical items to match this for (int i = 0; i < categoryRowLength; i++) { // check we have not gone out of range of the available news if (i < items.length) { physicalItems[category][i].setTitle(items[i].getTitle()); physicalItems[category][i].setId(items[i].getId()); // try and get an thumbnail for this item byte[] thumbBytes = items[i].getThumbnailBytes(); // check if any image data was returned if (Arrays.equals(thumbBytes, ReaderActivity.NO_THUMBNAIL_URL_CODE)) { // set the image to the no thumbnail image physicalItems[category][i].setImage(R.drawable.no_thumb); physicalItems[category][i].setImageLoaded(false); } else if (thumbBytes != null) { // try to construct an image out of the bytes given by the database Bitmap imageBitmap = BitmapFactory.decodeByteArray(thumbBytes, 0, thumbBytes.length); // load the image into a bitmap physicalItems[category][i].setImage(imageBitmap); physicalItems[category][i].setImageLoaded(true); } else { // set the image to the default grey image physicalItems[category][i].setImage(R.drawable.no_thumb_grey); physicalItems[category][i].setImageLoaded(false); } } } } } private void categoryLoadFinished(String category) { // the database has finished loading a category, we can update // FIXME very inefficient way to turn (string) name into (int) id int id = 0; // the id of the category for (int i = 0; i < categoryNames.length; i++) { // check if the name we have been given matches this category if (category.equals(categoryNames[i])) { id = i; } } displayCategoryItems(id); // redisplay this category } private void updateItemThumb(int id) { // loop through categories for (int i = 0; i < physicalItems.length; i++) { for (int t = 0; t < physicalItems[i].length; t++) { if (physicalItems[i][t].getId() == id) { // try and get an image for this item byte[] imageBytes = database.getThumbnail(id); // check if any image data was returned if (Arrays.equals(imageBytes, ReaderActivity.NO_THUMBNAIL_URL_CODE)) { // sets the image to the no thumbnail image physicalItems[i][t].setImage(R.drawable.no_thumb); physicalItems[i][t].setImageLoaded(false); } else if (imageBytes != null) { // try to construct an image out of the bytes given by the database Bitmap imageBitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); // load the image into a bitmap physicalItems[i][t].setImage(imageBitmap); physicalItems[i][t].setImageLoaded(true); } else { // set the image to the no thumbnail loaded image physicalItems[i][t].setImage(R.drawable.no_thumb_grey); physicalItems[i][t].setImageLoaded(false); } } } } } private void loadUnloadedThumbs() { // find unloaded images for(int i = 0; i < physicalItems.length; i++) { for(int j = 0; j < physicalItems[i].length; j++) { // only try and load the images if the item is set if(!physicalItems[i][j].isImageLoaded() && physicalItems[i][j].isItem()) { Bundle bundle = new Bundle(); bundle.putInt(ResourceService.KEY_ITEM_ID, physicalItems[i][j].getId()); service.sendMessageToService(ResourceService.MSG_LOAD_THUMB, bundle); } } } } }