Android Open Source - TechDissected Article Fragment






From Project

Back to project page TechDissected.

License

The source code is released under:

Apache License

If you think the Android project TechDissected 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.pkmmte.techdissected.fragment;
/*from w  w w  .  j  a  v a2  s .co  m*/
import android.app.ActionBar;
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.pkmmte.pkrss.Article;
import com.pkmmte.pkrss.PkRSS;
import com.pkmmte.techdissected.R;
import com.pkmmte.techdissected.activity.ArticleActivity;
import com.pkmmte.techdissected.util.Dialogs;
import com.pkmmte.techdissected.util.Utils;
import com.pkmmte.techdissected.view.CustomShareActionProvider;
import com.pkmmte.techdissected.view.FlowLayout;
import com.pkmmte.techdissected.view.PkScrollView;
import com.squareup.picasso.Picasso;

public class ArticleFragment extends Fragment {
  // Article
  private Article article;

  // Action Bar
  private ActionBar actionBar;
  private Drawable actionBarDrawable;
  private CustomShareActionProvider mShareActionProvider;
  private MenuItem menuFavorite;

  // WebView params
  private final String base = "file:///android_asset/";
  private final String mime = "text/html";
  private final String encoding = "utf-8";
  private final String history = null;

  // Parallax/Fading helper variables
  private int lastTopValue = 0;
  private int headerHeight;
  private int newAlpha;
  private float ratio;

  // Views
  private PkScrollView mScroll;
  private FlowLayout tagContainer;
  private FrameLayout imgContainer;
  private ImageView imgBanner;
  private TextView txtTitle;
  private TextView txtAuthor;
  private TextView txtDate;
  private WebView webView;

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    View view = inflater.inflate(R.layout.fragment_article, container, false);
    initActionBar();
    initViews(view);
    return view;
  }

  @Override
  public void onStart() {
    super.onStart();

    // Attempt to get article content
    retrieveContent();

    // Configure WebView
    setupWebView();

    // Show article content, if available
    showContent();

    // Let the SwipeLayout know which is the ScrollView
    ((ArticleActivity) getActivity()).setScrollTarget(mScroll);

    // Mark article as read
    if(article != null)
      article.markRead();

    // Change favorite icon state, if possible
    if(article != null && menuFavorite != null)
      menuFavorite.setIcon(article.isFavorite() ? R.drawable.ic_action_favorite_full : R.drawable.ic_action_favorite_empty);

    // Hacky custom fix for supporting FAB with sticky header
    mScroll.setExtraTopOffset(getResources().getDimensionPixelSize(R.dimen.action_height));

    // Scroll listener for parallax/fading effect
    mScroll.setOnScrollListener(new PkScrollView.PkScrollViewListener() {
      @Override
      public void onScrollChanged(PkScrollView scrollView, int x, int y, int oldx, int oldy) {
        parallaxBanner();
        fadeActionBar(y);
      }
    });
  }

  @Override
  public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
  {
    menu.clear();
    inflater.inflate(R.menu.article, menu);
    menuFavorite = menu.findItem(R.id.action_favorite);
    mShareActionProvider = (CustomShareActionProvider) menu.findItem(R.id.action_share).getActionProvider();
    setupShare();

    if(article != null)
      menuFavorite.setIcon(article.isFavorite() ? R.drawable.ic_action_favorite_full : R.drawable.ic_action_favorite_empty);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item)
  {
    switch (item.getItemId())
    {
      case android.R.id.home:
        getActivity().finish();

        return true;
      case R.id.action_favorite:
        if(article == null) {
          Toast.makeText(getActivity(), "Error loading article!", Toast.LENGTH_SHORT).show();
          return true;
        }

        boolean favorite = !article.isFavorite();
        if (article.saveFavorite(favorite))
          item.setIcon(favorite ? R.drawable.ic_action_favorite_full : R.drawable.ic_action_favorite_empty);

        return true;
      case R.id.action_refresh:
        // TODO
        return true;
      case R.id.action_unread:
        if(article == null) {
          Toast.makeText(getActivity(), "Error loading article!", Toast.LENGTH_SHORT).show();
          return true;
        }

        if(article.markRead(false))
          item.setVisible(false);
        else
          Toast.makeText(getActivity(), "Unable to mark article as read. Please try again.", Toast.LENGTH_SHORT).show();

        return true;
      case R.id.action_browser:
        if(article != null && article.getSource() != null)
          startActivity(new Intent(Intent.ACTION_VIEW).setData(article.getSource()));

        return true;
      default:
        return super.onOptionsItemSelected(item);
    }
  }

  public void toggleActionItems(Menu menu, boolean drawerOpen) {
    menu.findItem(R.id.action_share).setVisible(!drawerOpen);
    menu.findItem(R.id.action_favorite).setVisible(!drawerOpen);
    menu.findItem(R.id.action_browser).setVisible(!drawerOpen);
  }

  private void initActionBar() {
    // Get action bar instance
    actionBar = getActivity().getActionBar();

    // Enable the action bar home/up button
    actionBar.setHomeButtonEnabled(true);
    actionBar.setDisplayHomeAsUpEnabled(true);

    // Set custom fading drawable
    actionBarDrawable = new ColorDrawable(getResources().getColor(R.color.action_background));
    actionBarDrawable.setAlpha(0);
    actionBar.setBackgroundDrawable(actionBarDrawable);

    // Older versions require this callback
    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
      actionBarDrawable.setCallback( new Drawable.Callback() {
        @Override
        public void invalidateDrawable(Drawable who) {
          actionBar.setBackgroundDrawable(who);
        }

        @Override
        public void scheduleDrawable(Drawable who, Runnable what, long when) {
        }

        @Override
        public void unscheduleDrawable(Drawable who, Runnable what) {
        }
      });
    }
  }

  private void initViews(View v) {
    mScroll = (PkScrollView) v.findViewById(R.id.stickyScroll);
    tagContainer = (FlowLayout) v.findViewById(R.id.tagContainer);
    imgContainer = (FrameLayout) v.findViewById(R.id.imgContainer);
    imgBanner = (ImageView) v.findViewById(R.id.imgBanner);
    txtTitle = (TextView) v.findViewById(R.id.txtTitle);
    txtAuthor = (TextView) v.findViewById(R.id.txtAuthor);
    txtDate = (TextView) v.findViewById(R.id.txtDate);
    webView = (WebView) v.findViewById(R.id.webView);
  }

  private void retrieveContent() {
    Bundle bundle = getArguments();
    article = bundle.getParcelable(PkRSS.KEY_ARTICLE);
  }

  private void showContent() {
    // No content available; end here
    if(article == null) {
      Toast.makeText(getActivity(), "Error retrieving article!", Toast.LENGTH_SHORT).show();
      return;
    }

    // Attempt to configure share
    setupShare();

    // Asynchronously load the banner image
    Picasso.with(getActivity()).load(article.getImage()).placeholder(R.drawable.placeholder).into(imgBanner);

    // Expand banner upon click
    imgContainer.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Dialogs.getImageDialog(getActivity(), article.getImage()).show();
      }
    });

    // Set header text
    txtTitle.setText(article.getTitle());
    txtAuthor.setText(article.getAuthor());
    txtDate.setText(Utils.getRelativeDate(article.getDate()));

    // Load actual article content async, after the view is drawn
    webView.loadDataWithBaseURL(base, getCleanContent(), mime, encoding, history);

    // End here if tags are already loaded (Prevent duplicates)
    if(tagContainer.getChildCount() > 0)
      return;

    // Loop through tags to create views and add them to the container
    final LayoutInflater inflater = getActivity().getLayoutInflater();
    for(String tag : article.getTags()) {
      Button btnTag = (Button) inflater.inflate(R.layout.tag, tagContainer, false);
      btnTag.setText(tag);
      tagContainer.addView(btnTag);
    }
  }

  private void parallaxBanner()
  {
    Rect rect = new Rect();
    imgBanner.getLocalVisibleRect(rect);
    if (lastTopValue != rect.top){
      lastTopValue = rect.top;
      imgBanner.setY((float) (rect.top/2.0));
    }
  }

  private void fadeActionBar(int y) {
    headerHeight = imgBanner.getHeight() - actionBar.getHeight();
    ratio = (float) Math.min(Math.max(y, 0), headerHeight) / headerHeight;
    newAlpha = (int) (ratio * 255);
    actionBarDrawable.setAlpha(newAlpha);
  }

  private void setupWebView() {
    // Chrome Client for dynamic content
    webView.setWebChromeClient(new WebChromeClient());

    // Enable javascript & set vertical only
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
    webView.setHorizontalScrollBarEnabled(false);

    // Make sure it doesn't move horizontally
    webView.setOnTouchListener(new View.OnTouchListener() {
      private float downX;

      public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN: {
            // Save X value
            downX = event.getX();
          }
          break;
          case MotionEvent.ACTION_MOVE:
          case MotionEvent.ACTION_CANCEL:
          case MotionEvent.ACTION_UP: {
            // Set X so it doesn't move
            event.setLocation(downX, event.getY());
          }
          break;
        }

        return false;
      }
    });

    // Catch content clicks and handle them appropriately
    webView.setWebViewClient(new WebViewClient() {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (Utils.containsImage(url))
          Dialogs.getImageDialog(getActivity(), Uri.parse(url)).show();
        else startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));

        return true;
      }
    });

    // Workaround to fix background color
    webView.setBackgroundColor(getResources().getColor(R.color.app_background2));
  }

  /**
   * Sets up the share intent.
   * Will return prematurely if either the ShareActionProvider
   * or current article are null/invalid.
   */
  private void setupShare() {
    // Can't configure if null
    if (mShareActionProvider == null)
      return;

    // This won't do any good without data to use
    if(article == null || article.getSource() == null)
      return;

    // Build share content text
    String shareText = article.getTitle() + "\n\n" + article.getSource().toString();

    // Create and set the share intent
    Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareText);
    mShareActionProvider.setShareIntent(shareIntent);
  }

  private String getCleanContent() {
    if(article == null)
      return null;

    return "<html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" /></head><body>" + article.getContent() + "</body></head>";
  }

  public static ArticleFragment newInstance(Article article)
  {
    ArticleFragment mFragment = new ArticleFragment();
    Bundle args = new Bundle();
    args.putParcelable(PkRSS.KEY_ARTICLE, article);
    mFragment.setArguments(args);
    return mFragment;
  }
}




Java Source Code List

com.pkmmte.techdissected.ApplicationTest.java
com.pkmmte.techdissected.activity.ArticleActivity.java
com.pkmmte.techdissected.activity.MainActivity.java
com.pkmmte.techdissected.activity.SearchActivity.java
com.pkmmte.techdissected.adapter.AuthorAdapter.java
com.pkmmte.techdissected.adapter.CreditsLibraryAdapter.java
com.pkmmte.techdissected.adapter.FeedAdapter.java
com.pkmmte.techdissected.adapter.NavDrawerAdapter.java
com.pkmmte.techdissected.adapter.SettingsAdapter.java
com.pkmmte.techdissected.fragment.AboutFragment.java
com.pkmmte.techdissected.fragment.ArticleFragment.java
com.pkmmte.techdissected.fragment.FavoritesFragment.java
com.pkmmte.techdissected.fragment.FeedFragment.java
com.pkmmte.techdissected.fragment.SettingsFragment.java
com.pkmmte.techdissected.model.Author.java
com.pkmmte.techdissected.model.CreditsLibraryItem.java
com.pkmmte.techdissected.model.ListBuilder.java
com.pkmmte.techdissected.model.SettingsItem.java
com.pkmmte.techdissected.util.Base64DecoderException.java
com.pkmmte.techdissected.util.Base64.java
com.pkmmte.techdissected.util.Constants.java
com.pkmmte.techdissected.util.Dialogs.java
com.pkmmte.techdissected.util.IabException.java
com.pkmmte.techdissected.util.IabHelper.java
com.pkmmte.techdissected.util.IabResult.java
com.pkmmte.techdissected.util.Inventory.java
com.pkmmte.techdissected.util.Purchase.java
com.pkmmte.techdissected.util.RoundTransform.java
com.pkmmte.techdissected.util.Security.java
com.pkmmte.techdissected.util.SkuDetails.java
com.pkmmte.techdissected.util.Utils.java
com.pkmmte.techdissected.view.BakedBezierInterpolator.java
com.pkmmte.techdissected.view.CustomShareActionProvider.java
com.pkmmte.techdissected.view.FlowLayout.java
com.pkmmte.techdissected.view.HeaderGridView.java
com.pkmmte.techdissected.view.PkDrawerLayout.java
com.pkmmte.techdissected.view.PkScrollView.java
com.pkmmte.techdissected.view.PkSwipeRefreshLayout.java
com.pkmmte.techdissected.view.StickyScrollView.java
com.pkmmte.techdissected.view.SwipeProgressBar.java