Java tutorial
/* * This file is part of LoLin1. * * LoLin1 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LoLin1 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LoLin1. If not, see <http://www.gnu.org/licenses/>. * * Created by Jorge Antonio Diaz-Benito Soriano. */ package org.jorge.cmp.ui.fragment; import android.app.Activity; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.ScrollView; import android.widget.TextView; import com.melnykov.fab.FloatingActionButton; import org.jorge.cmp.LoLin1Application; import org.jorge.cmp.R; import org.jorge.cmp.datamodel.FeedArticle; import org.jorge.cmp.datamodel.LoLin1Account; import org.jorge.cmp.datamodel.Realm; import org.jorge.cmp.io.database.SQLiteDAO; import org.jorge.cmp.io.prefs.PreferenceAssistant; import org.jorge.cmp.ui.component.StickyParallaxNotifyingScrollView; import org.jorge.cmp.util.PicassoUtils; import java.util.Arrays; import java.util.concurrent.Executors; public class ArticleReaderFragment extends Fragment { public static final String KEY_ACCOUNT = "KEY_ACCOUNT"; private static Class mClass; private Context mContext; private int mDefaultImageId; private String TAG; private FeedArticle mArticle; public static final String KEY_ARTICLE = "ARTICLE"; private ActionBarActivity mActivity; @SuppressWarnings("FieldCanBeLocal") private Drawable mActionBarBackgroundDrawable; private LoLin1Account mAccount; private final Drawable.Callback mDrawableCallback = new Drawable.Callback() { @Override public void invalidateDrawable(Drawable who) { final ActionBar actionBar = mActivity.getSupportActionBar(); if (actionBar != null) actionBar.setBackgroundDrawable(who); } @Override public void scheduleDrawable(Drawable who, Runnable what, long when) { } @Override public void unscheduleDrawable(Drawable who, Runnable what) { } }; private ActionBar mActionBar; private float mOriginalElevation; private FloatingActionButton mMarkAsReadFab; public static Fragment newInstance(Context context, FeedArticle article, Class c, LoLin1Account acc) { Bundle args = new Bundle(); args.putParcelable(ArticleReaderFragment.KEY_ARTICLE, article); int errorResId = R.drawable.feed_article_image_placeholder; args.putInt(FeedListFragment.ERROR_RES_ID_KEY, errorResId); args.putParcelable(ArticleReaderFragment.KEY_ACCOUNT, acc); mClass = c; return ArticleReaderFragment.instantiate(context, ArticleReaderFragment.class.getName(), args); } @Override public void onAttach(Activity activity) { super.onAttach(activity); mContext = LoLin1Application.getInstance().getContext(); mActivity = (ActionBarActivity) activity; final Bundle args = getArguments(); if (args == null) throw new IllegalStateException("ArticleReader created without arguments"); mArticle = args.getParcelable(KEY_ARTICLE); TAG = mArticle.getUrl(); mDefaultImageId = args.getInt(FeedListFragment.ERROR_RES_ID_KEY); mAccount = args.getParcelable(KEY_ACCOUNT); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.actionbar_article_reader, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.home: case R.id.homeAsUp: mActivity.onBackPressed(); case R.id.action_browse_to: mArticle.requestBrowseToAction(mContext); return Boolean.TRUE; case R.id.action_share: mArticle.requestShareAction(mContext); return Boolean.TRUE; default: return super.onOptionsItemSelected(item); } } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { setHasOptionsMenu(Boolean.TRUE); final View ret = inflater.inflate(R.layout.fragment_article_reader, container, Boolean.FALSE); View mHeaderView = ret.findViewById(R.id.image); PicassoUtils.loadInto(mContext, mArticle.getImageUrl(), mDefaultImageId, (android.widget.ImageView) mHeaderView, TAG); final String title = mArticle.getTitle(); mHeaderView.setContentDescription(title); ((TextView) ret.findViewById(R.id.title)).setText(title); WebView contentView = (WebView) ret.findViewById(android.R.id.text1); WebSettings webViewSettings = contentView.getSettings(); contentView.setOverScrollMode(View.OVER_SCROLL_NEVER); webViewSettings.setJavaScriptCanOpenWindowsAutomatically(Boolean.TRUE); webViewSettings.setBuiltInZoomControls(Boolean.FALSE); contentView.setBackgroundColor(0x00000000); //I wonder why the default background is white contentView.loadData(mArticle.getPreviewText(), "text/html; charset=UTF-8", "UTF-8"); mActionBar = mActivity.getSupportActionBar(); mActionBar.setDisplayHomeAsUpEnabled(Boolean.TRUE); mActionBarBackgroundDrawable = new ColorDrawable( mContext.getResources().getColor(R.color.toolbar_background)); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { mActionBarBackgroundDrawable.setCallback(mDrawableCallback); } mActionBar.setBackgroundDrawable(mActionBarBackgroundDrawable); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mOriginalElevation = mActionBar.getElevation(); mActionBar.setElevation(0); //So that the shadow of the ActionBar doesn't show over // the article title } mActionBar.setTitle(mActivity.getString(R.string.section_title_article_reader)); StickyParallaxNotifyingScrollView scrollView = (StickyParallaxNotifyingScrollView) ret .findViewById(R.id.scroll_view); scrollView.setOnScrollChangedListener(mOnScrollChangedListener); scrollView.smoothScrollTo(0, 0); if (!mArticle.isRead()) { mMarkAsReadFab = (FloatingActionButton) ret.findViewById(R.id.fab_button_mark_as_read); mMarkAsReadFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { markArticleAsRead(mArticle); if (mMarkAsReadFab.isShown()) mMarkAsReadFab.hide(); } private void markArticleAsRead(FeedArticle article) { final Realm r = Realm.getInstanceByRealmId(ArticleReaderFragment.this.mAccount.getRealmEnum()); String l = PreferenceAssistant.readSharedString(mContext, PreferenceAssistant.PREF_LANG, null); if (l == null || !Arrays.asList(r.getLocales()).contains(l)) { l = r.getLocales()[0]; PreferenceAssistant.writeSharedString(mContext, PreferenceAssistant.PREF_LANG, l); } final Class newsClass = NewsListFragment.class; final Class communityClass = CommunityListFragment.class; final Class schoolClass = SchoolListFragment.class; String tableName; if (mClass == newsClass) { if (l == null || !Arrays.asList(r.getLocales()).contains(l)) { l = r.getLocales()[0]; PreferenceAssistant.writeSharedString(mContext, PreferenceAssistant.PREF_LANG, l); } tableName = SQLiteDAO.getNewsTableName(r, l); } else if (mClass == communityClass) { tableName = SQLiteDAO.getCommunityTableName(); } else if (mClass == schoolClass) { tableName = SQLiteDAO.getSchoolTableName(); } else { throw new IllegalArgumentException( "Feed list fragment class " + mClass.getCanonicalName() + " not recognized."); } new AsyncTask<Object, Void, Void>() { @Override protected Void doInBackground(Object... params) { SQLiteDAO.getInstance().markArticleAsRead((FeedArticle) params[0], (String) params[1]); return null; } }.executeOnExecutor(Executors.newSingleThreadExecutor(), article, tableName); article.markAsRead(); } }); mMarkAsReadFab.hide(); mMarkAsReadFab.setVisibility(View.VISIBLE); showMarkAsReadFabIfItProceeds(); } return ret; } private void showMarkAsReadFabIfItProceeds() { if (!mArticle.isRead()) mMarkAsReadFab.show(); } private StickyParallaxNotifyingScrollView.OnScrollChangedListener mOnScrollChangedListener = new StickyParallaxNotifyingScrollView.OnScrollChangedListener() { public void onScrollChanged(ScrollView who, int l, int t, int oldL, int oldT) { if (mMarkAsReadFab != null) if (!who.canScrollVertically(1) || !who.canScrollVertically(-1)) { showMarkAsReadFabIfItProceeds(); } else if (t < oldT) { showMarkAsReadFabIfItProceeds(); } else if (t > oldT) { if (mMarkAsReadFab.isShown()) mMarkAsReadFab.hide(); } } }; @Override public void onDestroy() { super.onDestroy(); PicassoUtils.cancel(mContext, TAG); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mActionBar.setElevation(mOriginalElevation); } } }