Merge pull request #391 from ojiikun/master

Android: Story Nav Overlay
This commit is contained in:
Samuel Clay 2013-08-15 13:52:51 -07:00
commit a96fa2db7d
23 changed files with 175 additions and 34 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="@drawable/overlay_left_pressed" />
<item android:state_enabled="false" android:drawable="@drawable/overlay_left_disabled" />
<item android:state_enabled="true" android:drawable="@drawable/overlay_left_enabled" />
</selector>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="@drawable/overlay_right_pressed" />
<item android:state_enabled="false" android:drawable="@drawable/overlay_right_disabled" />
<item android:state_enabled="true" android:drawable="@drawable/overlay_right_enabled" />
</selector>

View file

@ -14,4 +14,35 @@
android:layout_height="1dip"
android:layout_alignParentTop="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp"
android:layout_marginRight="8dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true" >
<Button
android:id="@+id/reading_overlay_left"
android:layout_width="52dp"
android:layout_height="41dp"
android:background="@drawable/selector_overlay_bg_left"
android:textSize="14sp"
android:padding="6dp"
android:onClick="overlayLeft" />
<Button
android:id="@+id/reading_overlay_right"
android:layout_width="125dp"
android:layout_height="41dp"
android:background="@drawable/selector_overlay_bg_right"
android:text="@string/overlay_next"
android:textColor="@color/half_darkgray"
android:textSize="14sp"
android:padding="6dp"
android:onClick="overlayRight" />
</LinearLayout>
</RelativeLayout>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<com.newsblur.view.NonfocusScrollview xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/reading_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/item_background" >
@ -41,4 +42,4 @@
</LinearLayout>
</com.newsblur.view.NonfocusScrollview>
</com.newsblur.view.NonfocusScrollview>

View file

@ -46,7 +46,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp" >
android:layout_marginRight="20dp"
android:layout_marginBottom="50dp" >
<LinearLayout
android:id="@+id/reading_friend_comment_container"

View file

@ -58,6 +58,9 @@
<string name="save_this">SAVE THIS STORY</string>
<string name="share_this">SHARE THIS STORY</string>
<string name="overlay_next">NEXT</string>
<string name="overlay_done">DONE</string>
<string name="reply_to">Reply to \"%s\"</string>
<string name="alert_dialog_ok">Okay</string>

View file

@ -17,7 +17,6 @@ import com.newsblur.util.StoryOrder;
public class AllSharedStoriesReading extends Reading {
private Cursor stories;
private int currentPage;
private boolean requestingPage = false;
private boolean stopLoading = false;
@ -80,11 +79,8 @@ public class AllSharedStoriesReading extends Reading {
@Override
public void updateAfterSync() {
setSupportProgressBarIndeterminateVisibility(false);
stories.requery();
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
requestingPage = false;
super.updateAfterSync();
}
@Override

View file

@ -17,7 +17,6 @@ import com.newsblur.util.StoryOrder;
public class AllStoriesReading extends Reading {
private Cursor stories;
private int currentPage;
private ArrayList<String> feedIds;
private boolean stopLoading = false;
@ -81,11 +80,8 @@ public class AllStoriesReading extends Reading {
@Override
public void updateAfterSync() {
setSupportProgressBarIndeterminateVisibility(false);
stories.requery();
requestedPage = false;
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
super.updateAfterSync();
}
@Override

View file

@ -69,11 +69,8 @@ public class FeedReading extends Reading {
@Override
public void updateAfterSync() {
setSupportProgressBarIndeterminateVisibility(false);
stories.requery();
requestedPage = false;
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
super.updateAfterSync();
}
@Override

View file

@ -68,11 +68,8 @@ public class FolderReading extends Reading {
@Override
public void updateAfterSync() {
setSupportProgressBarIndeterminateVisibility(false);
stories.requery();
requestedPage = false;
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
super.updateAfterSync();
}
@Override

View file

@ -12,6 +12,9 @@ import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
@ -34,8 +37,9 @@ import com.newsblur.util.PrefsUtils;
import com.newsblur.util.ReadFilter;
import com.newsblur.util.StoryOrder;
import com.newsblur.util.UIUtils;
import com.newsblur.view.NonfocusScrollview.ScrollChangeListener;
public abstract class Reading extends NbFragmentActivity implements OnPageChangeListener, SyncUpdateFragment.SyncUpdateFragmentInterface, OnSeekBarChangeListener {
public abstract class Reading extends NbFragmentActivity implements OnPageChangeListener, SyncUpdateFragment.SyncUpdateFragmentInterface, OnSeekBarChangeListener, ScrollChangeListener {
public static final String EXTRA_FEED = "feed_selected";
public static final String EXTRA_POSITION = "feed_position";
@ -45,10 +49,14 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
public static final String EXTRA_FEED_IDS = "feed_ids";
private static final String TEXT_SIZE = "textsize";
private static final int OVERLAY_RANGE_TOP_DP = 50;
private static final int OVERLAY_RANGE_BOT_DP = 60;
protected int passedPosition;
protected int currentState;
protected ViewPager pager;
protected Button overlayLeft, overlayRight;
protected FragmentManager fragmentManager;
protected ReadingAdapter readingAdapter;
protected ContentResolver contentResolver;
@ -58,12 +66,18 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
private Set<Story> storiesToMarkAsRead;
private float overlayRangeTopPx;
private float overlayRangeBotPx;
@Override
protected void onCreate(Bundle savedInstanceBundle) {
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceBundle);
setContentView(R.layout.activity_reading);
this.overlayLeft = (Button) findViewById(R.id.reading_overlay_left);
this.overlayRight = (Button) findViewById(R.id.reading_overlay_right);
fragmentManager = getSupportFragmentManager();
@ -76,6 +90,10 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
this.apiManager = new APIManager(this);
// this value is expensive to compute but doesn't change during a single runtime
this.overlayRangeTopPx = (float) UIUtils.convertDPsToPixels(this, OVERLAY_RANGE_TOP_DP);
this.overlayRangeBotPx = (float) UIUtils.convertDPsToPixels(this, OVERLAY_RANGE_BOT_DP);
}
protected void setupPager() {
@ -93,6 +111,7 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
pager.setAdapter(readingAdapter);
pager.setCurrentItem(passedPosition);
readingAdapter.setCurrentItem(passedPosition);
this.enableOverlays();
}
@Override
@ -151,6 +170,8 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
}
}
// interface OnPageChangeListener
@Override
public void onPageScrollStateChanged(int arg0) {
}
@ -160,15 +181,49 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
}
@Override
public void onPageSelected(final int position) {
public void onPageSelected(int position) {
this.setOverlayAlpha(1.0f);
this.enableOverlays();
}
// interface ScrollChangeListener
@Override
public void scrollChanged(int hPos, int vPos, int currentWidth, int currentHeight) {
int scrollMax = currentHeight - findViewById(android.R.id.content).getMeasuredHeight();
int posFromBot = (scrollMax - vPos);
float newAlpha = 0.0f;
if (vPos < this.overlayRangeTopPx) {
float delta = this.overlayRangeTopPx - ((float) vPos);
newAlpha = delta / this.overlayRangeTopPx;
} else if (posFromBot < this.overlayRangeBotPx) {
float delta = this.overlayRangeBotPx - ((float) posFromBot);
newAlpha = delta / this.overlayRangeBotPx;
}
this.setOverlayAlpha(newAlpha);
}
private void setOverlayAlpha(float a) {
UIUtils.setViewAlpha(this.overlayLeft, a);
UIUtils.setViewAlpha(this.overlayRight, a);
}
private void enableOverlays() {
int page = this.pager.getCurrentItem();
this.overlayLeft.setEnabled(page > 0);
this.overlayRight.setEnabled(page < (this.readingAdapter.getCount()-1));
this.overlayRight.setText((page < (this.readingAdapter.getCount()-1)) ? R.string.overlay_next : R.string.overlay_done);
}
@Override
public void updateAfterSync() {
setSupportProgressBarIndeterminateVisibility(false);
stories.requery();
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
this.enableOverlays();
}
@Override
@ -176,6 +231,7 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
stories.requery();
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
this.enableOverlays();
}
public abstract void checkStoryCount(int position);
@ -246,7 +302,12 @@ public abstract class Reading extends NbFragmentActivity implements OnPageChange
public void onStopTrackingTouch(SeekBar seekBar) {
}
public void overlayRight(View v) {
pager.setCurrentItem(pager.getCurrentItem()+1, true);
}
public void overlayLeft(View v) {
pager.setCurrentItem(pager.getCurrentItem()-1, true);
}
}

View file

@ -12,7 +12,6 @@ import com.newsblur.service.SyncService;
public class SavedStoriesReading extends Reading {
private Cursor stories;
private int currentPage;
private boolean stopLoading = false;
private boolean requestedPage = false;
@ -66,11 +65,8 @@ public class SavedStoriesReading extends Reading {
@Override
public void updateAfterSync() {
setSupportProgressBarIndeterminateVisibility(false);
stories.requery();
requestedPage = false;
readingAdapter.notifyDataSetChanged();
checkStoryCount(pager.getCurrentItem());
super.updateAfterSync();
}
@Override

View file

@ -153,7 +153,7 @@ public class DatabaseConstants {
private static final String SOCIAL_INTELLIGENCE_BEST = " (" + DatabaseConstants.SOCIAL_FEED_POSITIVE_COUNT + ") > 0 ";
private static final String SUM_STORY_TOTAL = "storyTotal";
public static final String FEED_FILTER_FOCUS = " WHERE " + FEED_TABLE + "." + FEED_POSITIVE_COUNT + " > 0 ";
public static final String FEED_FILTER_FOCUS = FEED_TABLE + "." + FEED_POSITIVE_COUNT + " > 0 ";
private static String STORY_SUM_TOTAL = " CASE " +
"WHEN MAX(" + DatabaseConstants.STORY_INTELLIGENCE_AUTHORS + "," + DatabaseConstants.STORY_INTELLIGENCE_TAGS + "," + DatabaseConstants.STORY_INTELLIGENCE_TITLE + ") > 0 " +
@ -163,9 +163,9 @@ public class DatabaseConstants {
"ELSE " + DatabaseConstants.STORY_INTELLIGENCE_FEED + " " +
"END AS " + DatabaseConstants.SUM_STORY_TOTAL;
public static final String STORY_INTELLIGENCE_BEST = DatabaseConstants.SUM_STORY_TOTAL + " > 0 ";
public static final String STORY_INTELLIGENCE_SOME = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
public static final String STORY_INTELLIGENCE_ALL = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
private static final String STORY_INTELLIGENCE_BEST = DatabaseConstants.SUM_STORY_TOTAL + " > 0 ";
private static final String STORY_INTELLIGENCE_SOME = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
private static final String STORY_INTELLIGENCE_ALL = DatabaseConstants.SUM_STORY_TOTAL + " >= 0 ";
public static final String[] STORY_COLUMNS = {
STORY_AUTHORS, STORY_COMMENT_COUNT, STORY_CONTENT, STORY_DATE, STORY_SHARED_DATE, STORY_SHORTDATE, STORY_LONGDATE, STORY_TABLE + "." + STORY_FEED_ID, STORY_TABLE + "." + STORY_ID, STORY_INTELLIGENCE_AUTHORS, STORY_INTELLIGENCE_FEED, STORY_INTELLIGENCE_TAGS, STORY_INTELLIGENCE_TITLE,

View file

@ -355,7 +355,7 @@ public class FeedProvider extends ContentProvider {
String feedsQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
" INNER JOIN " + DatabaseConstants.FEED_TABLE +
" ON " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_ID + " = " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FEED_ID +
((selection == null) ? "" : selection) +
((selection == null) ? "" : " WHERE " + selection) +
" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE";
return db.rawQuery(feedsQuery, selectionArgs);

View file

@ -1,5 +1,6 @@
package com.newsblur.fragment;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@ -42,6 +43,7 @@ import com.newsblur.util.UIUtils;
import com.newsblur.util.ViewUtils;
import com.newsblur.view.FlowLayout;
import com.newsblur.view.NewsblurWebview;
import com.newsblur.view.NonfocusScrollview;
public class ReadingItemFragment extends Fragment implements ClassifierDialogFragment.TagUpdateCallback, ShareDialogFragment.SharedCallbackDialog {
@ -64,6 +66,7 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
private UserDetails user;
public String previouslySavedShareText;
private ImageView feedIcon;
private Reading activity;
public static ReadingItemFragment newInstance(Story story, String feedTitle, String feedFaviconColor, String feedFaviconFade, String feedFaviconBorder, String faviconText, String faviconUrl, Classifier classifier, boolean displayFeedDetails) {
ReadingItemFragment readingFragment = new ReadingItemFragment();
@ -83,6 +86,13 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
return readingFragment;
}
@Override
public void onAttach(Activity activity) {
if (activity instanceof Reading) {
this.activity = (Reading) activity;
}
super.onAttach(activity);
}
@Override
public void onCreate(Bundle savedInstanceState) {
@ -147,6 +157,9 @@ public class ReadingItemFragment extends Fragment implements ClassifierDialogFra
setupItemCommentsAndShares(view);
}
NonfocusScrollview scrollView = (NonfocusScrollview) view.findViewById(R.id.reading_scrollview);
scrollView.registerScrollChangeListener(this.activity);
return view;
}

View file

@ -9,6 +9,8 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.os.Build;
import android.view.View;
public class UIUtils {
@ -70,9 +72,20 @@ public class UIUtils {
* used throughout Android.
* See: http://bit.ly/MfsAUZ (Romain Guy's comment)
*/
public static int convertDPsToPixels(Context context, final int dps) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dps * scale + 0.5f);
}
/**
* Sets the alpha of a view in a manner that is safe to use before API version 11.
* If alpha isn't supported, just make the view invisible if the alpha is so low
* that it may as well be.
*/
public static void setViewAlpha(View v, float alpha) {
v.setVisibility((alpha > 0.001) ? View.VISIBLE : View.INVISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
v.setAlpha(alpha);
}
}
}

View file

@ -1,13 +1,19 @@
package com.newsblur.view;
import java.util.HashSet;
import java.util.Set;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.ScrollView;
public class NonfocusScrollview extends ScrollView {
private Set<ScrollChangeListener> changeListeners = new HashSet<ScrollChangeListener>();
public NonfocusScrollview(Context context) {
super(context);
}
@ -23,4 +29,22 @@ public class NonfocusScrollview extends ScrollView {
}
super.requestChildFocus(child, focused);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
int w = this.getChildAt(0).getMeasuredWidth();
int h = this.getChildAt(0).getMeasuredHeight();
for (ScrollChangeListener listener : this.changeListeners) {
listener.scrollChanged(l, t, w, h);
}
super.onScrollChanged(l, t, oldl, oldt);
}
public void registerScrollChangeListener(ScrollChangeListener listener) {
this.changeListeners.add(listener);
}
public interface ScrollChangeListener {
public void scrollChanged(int hPos, int vPos, int currentWidth, int currentHeight);
}
}