remove X more image prompt

implement pager-based browser for article images, enabled if more than one detected
add (unused) dimens for activity margins
This commit is contained in:
Andrew Dolgov 2014-10-29 16:23:07 +03:00
parent 7fd2e713b3
commit f8bc884ad3
15 changed files with 464 additions and 62 deletions

View File

@ -11,7 +11,7 @@ android {
}
lintOptions {
abortOnError false
abortOnError false
}
buildTypes {
@ -24,14 +24,14 @@ android {
dependencies {
compile project(':taskerlocaleapi')
compile 'com.jeremyfeinstein.slidingmenu:library:1.3@aar'
compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'
compile 'com.viewpagerindicator:library:2.4.1'
compile 'com.android.support:cardview-v7:21.+'
compile 'com.android.support:support-v4:19.1.0'
compile 'com.google.code.gson:gson:1.7.1'
compile 'com.android.support:appcompat-v7:19.1.0'
compile files('libs/dashclock-api-r1.1.jar')
compile files('libs/jsoup-1.6.1.jar')
compile files('libs/universal-image-loader-1.9.3.jar')
compile 'com.jeremyfeinstein.slidingmenu:library:1.3@aar'
compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'
compile 'com.viewpagerindicator:library:2.4.1'
compile 'com.android.support:cardview-v7:21.0.0'
compile 'com.android.support:support-v4:19.1.0'
compile 'com.google.code.gson:gson:1.7.1'
compile 'com.android.support:appcompat-v7:19.1.0'
}

View File

@ -16,7 +16,7 @@
<application
android:name=".GlobalState"
android:allowBackup="true"
android:backupAgent="org.fox.ttrss.util.PrefsBackupAgent"
android:backupAgent=".util.PrefsBackupAgent"
android:hardwareAccelerated="true"
android:icon="@drawable/icon"
android:label="@string/app_name" >
@ -92,7 +92,6 @@
android:excludeFromRecents="true"
android:label="@string/subscribe_name"
android:theme="@style/DarkDialogTheme" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
@ -100,7 +99,6 @@
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@ -207,7 +205,7 @@
android:name=".offline.OfflineUploadService"
android:enabled="true" />
<service
android:name="org.fox.ttrss.util.ImageCacheService"
android:name=".util.ImageCacheService"
android:enabled="true" />
<meta-data
@ -220,7 +218,6 @@
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
</intent-filter>
</receiver>
<receiver android:name=".widget.SmallWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
@ -251,6 +248,11 @@
android:name="description"
android:value="@string/app_name" />
</service>
<activity
android:name=".ArticleImagesPagerActivity"
android:label="Article Images" >
</activity>
</application>
</manifest>

View File

@ -0,0 +1,204 @@
package org.fox.ttrss;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.viewpagerindicator.UnderlinePageIndicator;
import java.util.ArrayList;
import java.util.List;
public class ArticleImagesPagerActivity extends ActionBarActivity {
private final String TAG = this.getClass().getSimpleName();
private ArrayList<String> m_urls;
private String m_title;
private class ArticleImagesPagerAdapter extends PagerAdapter implements View.OnClickListener {
private List<String> m_urls;
public ArticleImagesPagerAdapter(List<String> urls) {
super();
m_urls = urls;
}
public ArticleImagesPagerAdapter() {
super();
}
@Override
public int getCount() {
return m_urls.size();
}
@Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
String url = m_urls.get(position);
Log.d(TAG, "called for URL: " + url);
LayoutInflater inflater = (LayoutInflater) container.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.article_images_image, null);
ImageView imgView = (ImageView) view.findViewById(R.id.flavor_image);
imgView.setOnClickListener(this);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.resetViewBeforeLoading(true)
.cacheOnDisk(true)
.displayer(new FadeInBitmapDisplayer(200))
.build();
ImageAware imageAware = new ImageViewAware(imgView, false);
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.flavor_image_progress);
final View errorMessage = view.findViewById(R.id.flavor_image_error);
ImageLoader.getInstance().displayImage(url, imageAware, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String s, View view) {
}
@Override
public void onLoadingFailed(String s, View view, FailReason failReason) {
progressBar.setVisibility(View.GONE);
errorMessage.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
if (bitmap != null) {
if (bitmap.getWidth() < 128 || bitmap.getHeight() < 128) {
view.setVisibility(View.INVISIBLE);
errorMessage.setVisibility(View.VISIBLE);
} else {
view.setTag(s);
}
}
progressBar.setVisibility(View.GONE);
}
@Override
public void onLoadingCancelled(String s, View view) {
}
});
((ViewPager) container).addView(view, 0);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((FrameLayout)object);
}
@Override
public void onClick(View view) {
String url = (String) view.getTag();
if (url != null) {
Log.d(TAG, "click to open:" + url);
try {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.DarkTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.article_images_pager);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (savedInstanceState == null) {
m_urls = getIntent().getStringArrayListExtra("urls");
m_title = getIntent().getStringExtra("title");
} else {
m_urls = savedInstanceState.getStringArrayList("urls");
m_title = savedInstanceState.getString("title");
}
setTitle(m_title);
Log.d(TAG, "urls size: " + m_urls.size());
ArticleImagesPagerAdapter adapter = new ArticleImagesPagerAdapter(m_urls);
ViewPager pager = (ViewPager) findViewById(R.id.article_images_pager);
pager.setAdapter(adapter);
UnderlinePageIndicator indicator = (UnderlinePageIndicator)findViewById(R.id.article_images_indicator);
indicator.setViewPager(pager);
}
@Override
public void onSaveInstanceState(Bundle out) {
super.onSaveInstanceState(out);
out.putStringArrayList("urls", m_urls);
out.putString("title", m_title);
}
/* @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.article_images_pager, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} */
}

View File

@ -465,7 +465,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
}
m_activity.setProgressBarVisibility(false);
super.onPostExecute(result);
if (isAdded()) {
@ -670,7 +670,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
public ImageView menuButtonView;
public ViewGroup flavorImageHolder;
public ProgressBar flavorImageLoadingBar;
public TextView flavorImageMore;
public View flavorImageArrow;
}
private class ArticleListAdapter extends ArrayAdapter<Article> {
@ -764,7 +764,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
holder.menuButtonView = (ImageView) v.findViewById(R.id.article_menu_button);
holder.flavorImageHolder = (ViewGroup) v.findViewById(R.id.flavorImageHolder);
holder.flavorImageLoadingBar = (ProgressBar) v.findViewById(R.id.flavorImageLoadingBar);
holder.flavorImageMore = (TextView) v.findViewById(R.id.flavorImageMore);
holder.flavorImageArrow = v.findViewById(R.id.flavorImageArrow);
v.setTag(holder);
@ -860,10 +860,6 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
}
}
if (holder.flavorImageMore != null) {
holder.flavorImageMore.setVisibility(View.GONE);
}
if (holder.flavorImageView != null && m_prefs.getBoolean("headlines_show_flavor_image", true)) {
Document doc = Jsoup.parse(articleContent);
@ -872,7 +868,7 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
if (doc != null) {
//Element img = doc.select("img").first();
Elements imgs = doc.select("img");
final Elements imgs = doc.select("img");
Element img = imgs.first();
if (img != null) {
@ -887,7 +883,32 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
.resetViewBeforeLoading(true)
.cacheOnDisk(true)
.build();
holder.flavorImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
ArrayList<String> imgsList = new ArrayList<String>();
for (Element img : imgs) {
String imgSrc = img.attr("src");
if (imgSrc.indexOf("//") == 0)
imgSrc = "http:" + imgSrc;
imgsList.add(imgSrc);
}
Intent intent = new Intent(m_activity, ArticleImagesPagerActivity.class);
intent.putExtra("urls", imgsList);
intent.putExtra("title", article.title);
startActivityForResult(intent, 0);
m_activity.overridePendingTransition(android.R.anim.fade_in, 0);
}
});
final ViewGroup flavorImageHolder = holder.flavorImageHolder;
final ImageView flavorImageView = holder.flavorImageView;
final ProgressBar flavorImageLoadingBar = holder.flavorImageLoadingBar;
@ -896,9 +917,8 @@ public class HeadlinesFragment extends Fragment implements OnItemClickListener,
flavorImageHolder.setVisibility(View.VISIBLE);
if (imgs.size() > 1 && holder.flavorImageMore != null) {
holder.flavorImageMore.setVisibility(View.VISIBLE);
holder.flavorImageMore.setText(getString(R.string.flavor_image_more, imgs.size()-1));
if (imgs.size() > 1 && holder.flavorImageArrow != null) {
holder.flavorImageArrow.setVisibility(View.VISIBLE);
}
final boolean weNeedAnimation = MemoryCacheUtils.findCachedBitmapsForImageUri(imgSrc, ImageLoader.getInstance().getMemoryCache()).size() == 0;

View File

@ -1,12 +1,5 @@
package org.fox.ttrss.offline;
import org.fox.ttrss.CommonActivity;
import org.fox.ttrss.PreferencesActivity;
import org.fox.ttrss.R;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
@ -33,6 +26,13 @@ import android.widget.EditText;
import android.widget.SearchView;
import android.widget.TextView;
import org.fox.ttrss.CommonActivity;
import org.fox.ttrss.PreferencesActivity;
import org.fox.ttrss.R;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class OfflineActivity extends CommonActivity {
private final String TAG = this.getClass().getSimpleName();
@ -169,9 +169,9 @@ public class OfflineActivity extends CommonActivity {
.getDefaultSharedPreferences(getApplicationContext());
setAppTheme(m_prefs);
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
setProgressBarVisibility(false);

View File

@ -0,0 +1,96 @@
package org.fox.ttrss.util;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.util.AttributeSet;
import android.view.View;
//http://stackoverflow.com/questions/24723040/how-to-create-a-right-facing-arrow-using-xml-shapes-in-android
public class ArrowRight extends View {
private Paint arrowPaint;
private Path arrowPath;
private int arrowColor = 0xFF888888;
private float density;
private int diameter = 5, diameter_calc, radius_calc;
public ArrowRight(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
stuff();
}
public ArrowRight(Context context, AttributeSet attrs) {
super(context, attrs);
stuff();
}
public ArrowRight(Context context) {
super(context);
stuff();
}
private void stuff() {
//Getting density "dp"
density = getContext().getResources().getDisplayMetrics().scaledDensity;
//Calculating actual diameter
diameter_calc = (int) density * diameter;
radius_calc = diameter/2;
//Creating paint
arrowPaint = new Paint();
arrowPaint.setAntiAlias(true);
arrowPaint.setColor(arrowColor);
//Initialize path
arrowPath = new Path();
this.setWillNotDraw(false);
}
private int startX,startY, currentX, currentY;
protected void onDraw(Canvas c) {
startX = c.getWidth();
startY = c.getHeight()/2;
c.rotate(-45, startX, startY);
arrowPath.reset();
currentX = startX;
currentY = startY;
//Move to right end side center of the canvas
arrowPath.moveTo(currentX,currentY);
//Lets move up
currentY = radius_calc;
arrowPath.lineTo(currentX, currentY);
//Now draw circle
currentX-=radius_calc;
arrowPath.addCircle(currentX, radius_calc, radius_calc, Direction.CCW);
currentX-=radius_calc;
arrowPath.lineTo(currentX,currentY);
// Go to inner side center point
currentX = startX - diameter_calc;
currentY = startY - diameter_calc;
arrowPath.lineTo(currentX,currentY);
// Go left
currentX = startX - startY + radius_calc;
arrowPath.lineTo(currentX, currentY);
//Draw circle
currentY+=radius_calc;
c.drawCircle(currentX, currentY, radius_calc, arrowPaint);
currentY+=radius_calc;
arrowPath.lineTo(currentX, currentY);
//Go to start
arrowPath.lineTo(startX, startY);
c.drawPath(arrowPath, arrowPaint);
}
}

View File

@ -0,0 +1,29 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/flavorImageHolder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible"
android:text="@string/error_loading_image"
android:id="@+id/flavor_image_error" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/flavor_image_progress" />
<org.fox.ttrss.util.EnlargingImageView
android:id="@+id/flavor_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:visibility="visible" />
</FrameLayout>

View File

@ -0,0 +1,24 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/article_images"
android:layout_width="match_parent"
android:layout_height="match_parent">
/*
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"> */
<android.support.v4.view.ViewPager
android:id="@+id/article_images_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>
<com.viewpagerindicator.UnderlinePageIndicator
android:id="@+id/article_images_indicator"
android:layout_width="fill_parent"
android:layout_height="2dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" />
</RelativeLayout>

View File

@ -94,13 +94,13 @@
android:cropToPadding="true"
android:visibility="visible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(5 more)"
android:alpha="0.5"
android:layout_gravity="bottom|right"
android:id="@+id/flavorImageMore" />
<org.fox.ttrss.util.ArrowRight
android:layout_marginRight="4dp"
android:id="@+id/flavorImageArrow"
android:layout_width="64dp"
android:layout_gravity="center|right"
android:visibility="gone"
android:layout_height="64dp" />
</FrameLayout>
</TableRow>

View File

@ -94,13 +94,14 @@
android:cropToPadding="true"
android:visibility="visible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(5 more)"
android:alpha="0.5"
android:layout_gravity="bottom|right"
android:id="@+id/flavorImageMore" />
<org.fox.ttrss.util.ArrowRight
android:layout_marginRight="4dp"
android:id="@+id/flavorImageArrow"
android:layout_width="64dp"
android:layout_gravity="center|right"
android:visibility="gone"
android:layout_height="64dp" />
</FrameLayout>
</TableRow>

View File

@ -95,13 +95,14 @@
android:cropToPadding="true"
android:visibility="visible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(5 more)"
android:alpha="0.5"
android:layout_gravity="bottom|right"
android:id="@+id/flavorImageMore" />
<org.fox.ttrss.util.ArrowRight
android:layout_marginRight="4dp"
android:id="@+id/flavorImageArrow"
android:layout_width="64dp"
android:layout_gravity="center|right"
android:visibility="gone"
android:layout_height="64dp" />
</FrameLayout>
</TableRow>

View File

@ -95,13 +95,13 @@
android:cropToPadding="true"
android:visibility="visible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(5 more)"
android:alpha="0.5"
android:layout_gravity="bottom|right"
android:id="@+id/flavorImageMore" />
<org.fox.ttrss.util.ArrowRight
android:layout_marginRight="4dp"
android:id="@+id/flavorImageArrow"
android:layout_width="64dp"
android:layout_gravity="center|right"
android:visibility="gone"
android:layout_height="64dp" />
</FrameLayout>
</TableRow>

View File

@ -0,0 +1,9 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.fox.ttrss.ArticleImagesPagerActivity" >
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>

View File

@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@ -149,10 +149,12 @@
<string name="prefs_dim_status_bar">Dim status bar</string>
<string name="prefs_dim_status_bar_long">Dim status bar when reading</string>
<string name="article_comments">%1$d comments</string>
<plurals name="trial_mode_prompt">
<item quantity="one">Trial mode, only one day left.</item>
<item quantity="other">Trial mode, %1$d days left.</item>
</plurals>
<string name="trial_purchase">Unlock full version</string>
<string name="trial_expired">Trial expired</string>
<string name="trial_expired_message">To continue using Tiny Tiny RSS please unlock the full version by purchasing the key.</string>
@ -198,17 +200,21 @@
<string name="light_theme_is_not_supported_on_honeycomb">Light theme is not supported on Honeycomb</string>
<string name="pref_headlines_mark_read_scroll">Mark read on scroll</string>
<string name="pref_headlines_mark_read_scroll_long">Headlines will be marked read when scrolling past them</string>
<plurals name="mark_num_headlines_as_read">
<item quantity="one">Mark %1$d article as read?</item>
<item quantity="other">Mark %1$d articles as read?</item>
</plurals>
<string name="prefs_confirm_headlines_catchup">Confirm marking articles as read</string>
<string name="author_formatted">by %1$s</string>
<plurals name="n_unread_articles">
<item quantity="zero">No unread articles</item>
<item quantity="one">One unread article</item>
<item quantity="other">%1$d unread articles</item>
</plurals>
<string name="pref_headline_font_size">Headline text size</string>
<string name="context_confirm_catchup">Mark all articles in %1$s as read?</string>
<string name="theme_system">Device Default</string>
@ -233,4 +239,9 @@
<string name="pref_headlines_full_content">Show full content</string>
<string name="prefs_headlines_show_flavor_image">Show article image</string>
<string name="flavor_image_more">(%1$d more)</string>
<string name="title_activity_article_images_pager">ArticleImagesPagerActivity</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="error_loading_image">Error loading image.</string>
</resources>