Android Open Source - BBC-News-Reader Frontpage Fragment






From Project

Back to project page BBC-News-Reader.

License

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.

Java Source Code

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);
        }
      }
    }
  }
}




Java Source Code List

com.digitallizard.bbcnewsreader.ArticleActivity.java
com.digitallizard.bbcnewsreader.CategoryActivity.java
com.digitallizard.bbcnewsreader.CategoryChooserActivity.java
com.digitallizard.bbcnewsreader.CategoryChooserAdapter.java
com.digitallizard.bbcnewsreader.CategoryPagerAdapter.java
com.digitallizard.bbcnewsreader.Eula.java
com.digitallizard.bbcnewsreader.ItemAdapter.java
com.digitallizard.bbcnewsreader.ItemLayout.java
com.digitallizard.bbcnewsreader.Item.java
com.digitallizard.bbcnewsreader.RSSManager.java
com.digitallizard.bbcnewsreader.ReaderActivity.java
com.digitallizard.bbcnewsreader.ResourceInterface.java
com.digitallizard.bbcnewsreader.ResourceService.java
com.digitallizard.bbcnewsreader.ServiceManager.java
com.digitallizard.bbcnewsreader.SettingsActivity.java
com.digitallizard.bbcnewsreader.data.DatabaseHandler.java
com.digitallizard.bbcnewsreader.data.DatabaseHelper.java
com.digitallizard.bbcnewsreader.data.DatabaseProvider.java
com.digitallizard.bbcnewsreader.data.ItemClearer.java
com.digitallizard.bbcnewsreader.data.WrapBackwards.java
com.digitallizard.bbcnewsreader.fragments.ArticleFragment.java
com.digitallizard.bbcnewsreader.fragments.CategoryChooserFragment.java
com.digitallizard.bbcnewsreader.fragments.CategoryFragment.java
com.digitallizard.bbcnewsreader.fragments.FrontpageFragment.java
com.digitallizard.bbcnewsreader.resource.web.HtmlParser.java
com.digitallizard.bbcnewsreader.resource.web.ImageDownloader.java
com.digitallizard.bbcnewsreader.resource.web.QueueItem.java
com.digitallizard.bbcnewsreader.resource.web.WebManager.java
com.digitallizard.bbcnewsreader.widget.ReaderWidget.java
com.digitallizard.bbcnewsreader.widget.WidgetConfigActivity.java
com.hlidskialf.android.preference.SeekBarPreference.java