Merge pull request #808 from emasty/fast_actions_detail_view
Fast actions detail view
This commit is contained in:
commit
3b56c86f84
26 changed files with 677 additions and 41 deletions
|
@ -26,6 +26,7 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
@ -35,11 +36,13 @@ import android.util.SparseArray;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
@ -84,6 +87,14 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
// protected @BindView(R.id.bottomAppBar) BottomAppBar bottomAppBar;
|
||||
protected @BindView(R.id.progressIndicator) ProgressBar progressIndicator;
|
||||
//protected @BindView(R.id.btn_disable_incognito) ImageButton mBtnDisableIncognito;
|
||||
protected @BindView(R.id.fa_detail_bar) View fastActionDetailBar;
|
||||
protected @BindView(R.id.fa_collapse_layout) View fastActionCollapseLayout;
|
||||
protected @BindView(R.id.fa_star) AppCompatImageButton fastActionStar;
|
||||
protected @BindView(R.id.fa_mark_as_read) AppCompatImageButton fastActionRead;
|
||||
protected @BindView(R.id.fa_toggle) AppCompatImageButton fastActionToggle;
|
||||
protected @BindView(R.id.fa_open_in_browser) AppCompatImageButton fastActionOpenInBrowser;
|
||||
protected @BindView(R.id.fa_share) AppCompatImageButton fastActionShare;
|
||||
|
||||
|
||||
/**
|
||||
* The {@link ViewPager} that will host the section contents.
|
||||
|
@ -224,6 +235,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
}
|
||||
|
||||
mViewPager.addOnPageChangeListener(onPageChangeListener);
|
||||
this.initFastActionBar();
|
||||
|
||||
/*
|
||||
mBtnDisableIncognito.setOnClickListener(v -> {
|
||||
|
@ -232,6 +244,67 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
updateActionBarIcons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init fast action bar based on user settings.
|
||||
* Only show if user selected setting CB_SHOW_FAST_ACTIONS. Otherwise hide.
|
||||
*
|
||||
* author: emasty https://github.com/emasty
|
||||
*/
|
||||
private void initFastActionBar() {
|
||||
boolean showFastActions = mPrefs.getBoolean(SettingsActivity.CB_SHOW_FAST_ACTIONS, true);
|
||||
|
||||
if (showFastActions) {
|
||||
// Set click listener for buttons on action bar
|
||||
fastActionOpenInBrowser.setOnClickListener(v -> this.openInBrowser(currentPosition));
|
||||
fastActionShare.setOnClickListener(v -> this.share(currentPosition));
|
||||
fastActionToggle.setOnClickListener(v -> this.toggleFastActionBar());
|
||||
|
||||
RssItem rssItem = rssItems.get(currentPosition);
|
||||
boolean isStarred = rssItem.getStarred_temp();
|
||||
boolean isRead = rssItem.getRead_temp();
|
||||
|
||||
|
||||
fastActionStar.setOnClickListener(v -> NewsDetailActivity.this.toggleRssItemStarredState());
|
||||
fastActionStar.setImageResource(isStarred ? R.drawable.ic_action_star_dark : R.drawable.ic_action_star_border_dark);
|
||||
|
||||
|
||||
fastActionRead.setOnClickListener(v -> NewsDetailActivity.this.markRead(currentPosition));
|
||||
fastActionRead.setImageResource(isRead ? R.drawable.ic_check_box_white : R.drawable.ic_check_box_outline_blank_white);
|
||||
|
||||
fastActionDetailBar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
fastActionDetailBar.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands or shrinks the fast action bar to show/hide secondary functions
|
||||
*/
|
||||
private void toggleFastActionBar() {
|
||||
int currentState = fastActionCollapseLayout.getVisibility();
|
||||
switch (currentState) {
|
||||
case View.GONE:
|
||||
fastActionToggle.setImageResource(R.drawable.ic_fa_expand);
|
||||
fastActionCollapseLayout.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case View.VISIBLE:
|
||||
fastActionToggle.setImageResource(R.drawable.ic_fa_shrink);
|
||||
fastActionCollapseLayout.setVisibility(View.GONE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//((Animatable)fastActionToggle.getDrawable()).start();
|
||||
fastActionToggle.setScaleX(-1);
|
||||
}
|
||||
|
||||
private void toggleIncognitoMode() {
|
||||
// toggle incognito mode
|
||||
setIncognitoEnabled(!isIncognitoEnabled());
|
||||
|
@ -281,7 +354,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
public static SORT_DIRECTION getSortDirectionFromSettings(SharedPreferences prefs) {
|
||||
SORT_DIRECTION sDirection = SORT_DIRECTION.asc;
|
||||
String sortDirection = prefs.getString(SettingsActivity.SP_SORT_ORDER, "1");
|
||||
if (sortDirection.equals("1"))
|
||||
if ("1".equals(sortDirection))
|
||||
sDirection = SORT_DIRECTION.desc;
|
||||
return sDirection;
|
||||
}
|
||||
|
@ -355,8 +428,7 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
mPostDelayHandler.delayTimer();
|
||||
|
||||
Log.v("PAGE CHANGED", "PAGE: " + position + " - IDFEED: " + rssItems.get(position).getId());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
updateActionBarIcons();
|
||||
}
|
||||
}
|
||||
|
@ -396,20 +468,27 @@ public class NewsDetailActivity extends PodcastFragmentActivity {
|
|||
menuItem_PlayPodcast.setVisible(podcastAvailable);
|
||||
}
|
||||
|
||||
if(menuItem_Starred != null) {
|
||||
if (isStarred) {
|
||||
menuItem_Starred.setIcon(R.drawable.ic_action_star_dark);
|
||||
fastActionStar.setImageResource(R.drawable.ic_action_star_dark);
|
||||
} else {
|
||||
menuItem_Starred.setIcon(R.drawable.ic_action_star_border_dark);
|
||||
fastActionStar.setImageResource(R.drawable.ic_action_star_border_dark);
|
||||
}
|
||||
}
|
||||
|
||||
if(isStarred && menuItem_Starred != null)
|
||||
menuItem_Starred.setIcon(R.drawable.ic_action_star_dark);
|
||||
else if(menuItem_Starred != null)
|
||||
menuItem_Starred.setIcon(R.drawable.ic_action_star_border_dark);
|
||||
|
||||
if(isRead && menuItem_Read != null) {
|
||||
menuItem_Read.setIcon(R.drawable.ic_check_box_white);
|
||||
menuItem_Read.setChecked(true);
|
||||
}
|
||||
else if(menuItem_Read != null) {
|
||||
menuItem_Read.setIcon(R.drawable.ic_check_box_outline_blank_white);
|
||||
menuItem_Read.setChecked(false);
|
||||
}
|
||||
if(menuItem_Read != null) {
|
||||
if (isRead) {
|
||||
menuItem_Read.setIcon(R.drawable.ic_check_box_white);
|
||||
menuItem_Read.setChecked(true);
|
||||
fastActionRead.setImageResource(R.drawable.ic_check_box_white);
|
||||
} else {
|
||||
menuItem_Read.setIcon(R.drawable.ic_check_box_outline_blank_white);
|
||||
menuItem_Read.setChecked(false);
|
||||
fastActionRead.setImageResource(R.drawable.ic_check_box_outline_blank_white);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -182,10 +182,9 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
|
|||
mProgressBarLoading.setVisibility(View.GONE);
|
||||
// Make sure to sync the incognitio on retained views
|
||||
syncIncognitoState();
|
||||
this.addBottomPaddingForFastActions(mWebView);
|
||||
}
|
||||
|
||||
|
||||
|
||||
setUpGestureDetector();
|
||||
|
||||
return rootView;
|
||||
|
@ -339,8 +338,8 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
|
|||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
addBottomPaddingForFastActions(view);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
mWebView.setOnTouchListener((v, event) -> {
|
||||
|
@ -356,6 +355,30 @@ public class NewsDetailFragment extends Fragment implements RssItemToHtmlTask.Li
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add free space to bottom of web-site if Fast-Actions are switched on.
|
||||
* Otherwise the fast action bar might hide the article content.
|
||||
* Method to modify the body margins with JavaScript seems to be dirty, but no other
|
||||
* solution seems to be available.
|
||||
*
|
||||
* This method does (for unknown reasons) not work if WebView gets restored. The Javascript is
|
||||
* called but not executed.
|
||||
*
|
||||
* This is (only) a problem, if user swipes back in viewpager to already loaded articles.
|
||||
* Solution might be to switch to a different design.
|
||||
* - Bottom App Bar -- overall cleanest solution but interferes with current implementation
|
||||
* of Podcast Player
|
||||
* - Auto-hiding ActionBar. Hard to implement as scroll behaviour of WebView has to be used
|
||||
* for hiding/showing ActionBar.
|
||||
*
|
||||
* @param view WebView with article
|
||||
*/
|
||||
private void addBottomPaddingForFastActions(WebView view) {
|
||||
if (mPrefs.getBoolean(SettingsActivity.CB_SHOW_FAST_ACTIONS,true)) {
|
||||
view.loadUrl("javascript:document.body.style.marginBottom=\"100px\"; void 0");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given url in the selected view based on user settings (Custom Chrome Tabs, webview or external)
|
||||
*
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.content.SharedPreferences;
|
|||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
@ -40,6 +41,9 @@ import android.view.LayoutInflater;
|
|||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -52,6 +56,8 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -202,6 +208,7 @@ public class NewsReaderDetailFragment extends Fragment {
|
|||
Log.v(TAG, "onResume called!");
|
||||
|
||||
mMarkAsReadWhileScrollingEnabled = mPrefs.getBoolean(SettingsActivity.CB_MARK_AS_READ_WHILE_SCROLLING_STRING, false);
|
||||
this.initFastDoneAll(this.getView());
|
||||
|
||||
//When the fragment is instantiated by the xml file, onResume will be called twice
|
||||
if (onResumeCount >= 2) {
|
||||
|
@ -251,6 +258,21 @@ public class NewsReaderDetailFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init fast action for mark all as read shown as floating action bar button (fab)
|
||||
*
|
||||
* @param rootView root view of fragment
|
||||
*/
|
||||
protected void initFastDoneAll(View rootView) {
|
||||
FloatingActionButton fab_done_all = rootView.findViewById(R.id.fab_done_all);
|
||||
if (mPrefs.getBoolean(SettingsActivity.CB_SHOW_FAST_ACTIONS, true)) {
|
||||
fab_done_all.setVisibility(View.VISIBLE);
|
||||
fab_done_all.setOnTouchListener(new FastMarkReadMotionListener(rootView));
|
||||
} else {
|
||||
fab_done_all.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current RSS-View
|
||||
*/
|
||||
|
@ -654,5 +676,160 @@ public class NewsReaderDetailFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MotionListener for Floating Action Bar Button to mark all articles in current
|
||||
* news feed as marked without using the menu.
|
||||
*
|
||||
* A movement up is required to prevent accidentally marking articles as read.
|
||||
*/
|
||||
private class FastMarkReadMotionListener implements View.OnTouchListener {
|
||||
private View fabMarkAllAsRead;
|
||||
private ImageView targetView;
|
||||
|
||||
private boolean markAsRead = false;
|
||||
private float originX,
|
||||
originY;
|
||||
private float dx,
|
||||
dy;
|
||||
|
||||
public FastMarkReadMotionListener(View fabMarkAllAsRead) {
|
||||
this.fabMarkAllAsRead = fabMarkAllAsRead;
|
||||
this.targetView = (ImageView)fabMarkAllAsRead.findViewById(R.id.target_done_all);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
this.startUserInteractionProcess(v, event);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
this.moveFAB(v, event);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
this.stopUserInteractionProcess(v);
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Animation for user to drag all read button to target.
|
||||
* Once the button is moved to the target, a success animation is loaded and shown.
|
||||
*
|
||||
* @param v FAB moved by the user
|
||||
* @param event motion event for v
|
||||
*/
|
||||
|
||||
private void startUserInteractionProcess(View v, MotionEvent event) {
|
||||
// Save start location of movement and button
|
||||
this.originX = v.getX();
|
||||
this.originY = v.getY();
|
||||
this.dx = v.getX() - event.getRawX();
|
||||
this.dy = v.getY() - event.getRawY();
|
||||
this.markAsRead = false;
|
||||
|
||||
// Start animation of target
|
||||
this.targetView.setImageResource(R.drawable.fa_all_read_target);
|
||||
this.targetView.setVisibility(View.VISIBLE);
|
||||
((Animatable)this.targetView.getDrawable()).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle move event of FAB to mark all articles as read
|
||||
* Two things are done here:
|
||||
* - button location is changed
|
||||
* - it is checked iv button is moved into target area
|
||||
*
|
||||
* @param v FAB moved by the user
|
||||
* @param event motion event for v
|
||||
*/
|
||||
private void moveFAB(View v, MotionEvent event) {
|
||||
v.setX(event.getRawX() + this.dx);
|
||||
v.setY(event.getRawY() + this.dy);
|
||||
this.checkLocation(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if FAB to mark all as read was moved within the shown target area.
|
||||
* For location calculation, the actual location of the target view is read
|
||||
* and calculated if current move position is within the view area of the target view.
|
||||
*
|
||||
* @param evt MotionEvent of all read FAB
|
||||
*/
|
||||
private void checkLocation(MotionEvent evt) {
|
||||
// Location on screen for target is required as motion event returns location on screen
|
||||
int[] location = new int[2];
|
||||
this.targetView.getLocationOnScreen(location);
|
||||
|
||||
Rect r = new Rect(location[0], location[1],
|
||||
(location[0] + targetView.getWidth()),
|
||||
(location[1] + targetView.getHeight()));
|
||||
|
||||
if (r.contains((int)evt.getRawX(), (int)evt.getRawY())) {
|
||||
if (!this.markAsRead) {
|
||||
this.markAsRead = true;
|
||||
this.targetView.setImageResource(R.drawable.fa_all_read_target_success);
|
||||
((Animatable) this.targetView.getDrawable()).start();
|
||||
}
|
||||
} else {
|
||||
if (this.markAsRead) {
|
||||
this.markAsRead = false;
|
||||
this.targetView.setImageResource(R.drawable.fa_all_read_target);
|
||||
((Animatable) this.targetView.getDrawable()).start();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the user interaction
|
||||
* - FAB is animated back to original position
|
||||
* - A success animation is shown of all articles will be marked as read
|
||||
* - Target view is hidden again
|
||||
*
|
||||
* @param v view of fab
|
||||
*/
|
||||
private void stopUserInteractionProcess(View v) {
|
||||
if (this.markAsRead) {
|
||||
Animation anim_success = AnimationUtils.loadAnimation(NewsReaderDetailFragment.this.getContext(),
|
||||
R.anim.all_read_success);
|
||||
anim_success.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
v.animate().x(originX).y(originY).setDuration(100).setStartDelay(0).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
((Animatable)targetView.getDrawable()).stop();
|
||||
targetView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
//Nothing to do here for now
|
||||
}
|
||||
});
|
||||
this.targetView.startAnimation(anim_success);
|
||||
this.markAllAsReadForCurrentView();
|
||||
} else {
|
||||
this.targetView.setVisibility(View.INVISIBLE);
|
||||
v.animate().x(this.originX).y(this.originY).setDuration(100).setStartDelay(0).start();
|
||||
((Animatable)this.targetView.getDrawable()).stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all articles in current view as read.
|
||||
*/
|
||||
private void markAllAsReadForCurrentView() {
|
||||
DatabaseConnectionOrm dbConn2 = new DatabaseConnectionOrm(this.fabMarkAllAsRead.getContext());
|
||||
dbConn2.markAllItemsAsReadForCurrentView();
|
||||
NewsReaderDetailFragment.this.refreshCurrentRssView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ public class SettingsActivity extends AppCompatActivity {
|
|||
public static final String LV_CACHE_IMAGES_OFFLINE_STRING = "lv_cacheImagesOffline";
|
||||
|
||||
public static final String CB_MARK_AS_READ_WHILE_SCROLLING_STRING = "cb_MarkAsReadWhileScrolling";
|
||||
public static final String CB_SHOW_FAST_ACTIONS = "cb_ShowFastActions";
|
||||
public static final String CB_DISABLE_HOSTNAME_VERIFICATION_STRING = "cb_DisableHostnameVerification";
|
||||
public static final String CB_SKIP_DETAILVIEW_AND_OPEN_BROWSER_DIRECTLY_STRING = "cb_openInBrowserDirectly";
|
||||
public static final String CB_SHOW_NOTIFICATION_NEW_ARTICLES_STRING = "cb_showNotificationNewArticles";
|
||||
|
|
18
News-Android-App/src/main/res/anim/all_read_success.xml
Normal file
18
News-Android-App/src/main/res/anim/all_read_success.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<scale
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:toXScale="4.0"
|
||||
android:toYScale="4.0"
|
||||
android:pivotX="100%"
|
||||
android:pivotY="0%"
|
||||
android:duration="300" />
|
||||
<alpha
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:duration="300"
|
||||
/>
|
||||
</set>
|
BIN
News-Android-App/src/main/res/drawable-hdpi/fa_bg.9.png
Normal file
BIN
News-Android-App/src/main/res/drawable-hdpi/fa_bg.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
News-Android-App/src/main/res/drawable-mdpi/fa_bg.9.png
Normal file
BIN
News-Android-App/src/main/res/drawable-mdpi/fa_bg.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
5
News-Android-App/src/main/res/drawable-v21/fa_button.xml
Normal file
5
News-Android-App/src/main/res/drawable-v21/fa_button.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?android:colorControlHighlight">
|
||||
<item android:drawable="@drawable/ic_fa_main_bg" />
|
||||
</ripple>
|
BIN
News-Android-App/src/main/res/drawable-xhdpi/fa_bg.9.png
Normal file
BIN
News-Android-App/src/main/res/drawable-xhdpi/fa_bg.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
News-Android-App/src/main/res/drawable-xxhdpi/fa_bg.9.png
Normal file
BIN
News-Android-App/src/main/res/drawable-xxhdpi/fa_bg.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
BIN
News-Android-App/src/main/res/drawable-xxxhdpi/fa_bg.9.png
Normal file
BIN
News-Android-App/src/main/res/drawable-xxxhdpi/fa_bg.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8 KiB |
|
@ -0,0 +1,54 @@
|
|||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt" >
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="128dp"
|
||||
android:height="128dp"
|
||||
android:viewportWidth="128"
|
||||
android:viewportHeight="128">
|
||||
|
||||
<group
|
||||
android:name="scaleGroup"
|
||||
android:pivotX="64"
|
||||
android:pivotY="64"
|
||||
android:scaleX="0.5"
|
||||
android:scaleY="0.5"
|
||||
>
|
||||
<path
|
||||
android:pathData="M64.001,64m-60,0a60,60 0,1 1,119.999 0a60,60 0,1 1,-119.999 0"
|
||||
android:strokeWidth="6"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#68BDEC"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M64,64m-26.25,0a26.25,26.25 0,1 1,52.5 0a26.25,26.25 0,1 1,-52.5 0"
|
||||
android:fillColor="#68BDEC"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M68.969,58.656C68.603,58.291 68.012,58.291 67.647,58.656L62.359,63.944L63.681,65.266L68.969,59.969C69.325,59.612 69.325,59.013 68.969,58.656ZM72.944,58.647L63.681,67.909L60.419,64.656C60.053,64.291 59.463,64.291 59.097,64.656C58.731,65.022 58.731,65.613 59.097,65.978L63.016,69.897C63.381,70.262 63.972,70.262 64.338,69.897L74.266,59.978C74.631,59.612 74.631,59.022 74.266,58.656L74.256,58.656C73.9,58.281 73.309,58.281 72.944,58.647ZM53.8,65.988L57.719,69.906C58.084,70.272 58.675,70.272 59.041,69.906L59.697,69.25L55.122,64.656C54.756,64.291 54.166,64.291 53.8,64.656C53.434,65.022 53.434,65.622 53.8,65.988Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="nonZero"/>
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
|
||||
<target android:name="scaleGroup"> *
|
||||
<aapt:attr name="android:animation">
|
||||
<set>
|
||||
<objectAnimator
|
||||
android:duration="1000"
|
||||
android:propertyName="scaleY"
|
||||
android:repeatCount="infinite"
|
||||
android:repeatMode="restart"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.5" />
|
||||
<objectAnimator
|
||||
android:duration="1000"
|
||||
android:propertyName="scaleX"
|
||||
android:repeatCount="infinite"
|
||||
android:repeatMode="restart"
|
||||
android:valueFrom="1.0"
|
||||
android:valueTo="0.5" />
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
|
@ -0,0 +1,54 @@
|
|||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt" >
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="128dp"
|
||||
android:height="128dp"
|
||||
android:viewportWidth="128"
|
||||
android:viewportHeight="128">
|
||||
|
||||
<group
|
||||
android:name="scaleGroup"
|
||||
android:pivotX="64"
|
||||
android:pivotY="64"
|
||||
android:scaleX="0.5"
|
||||
android:scaleY="0.5"
|
||||
>
|
||||
<path
|
||||
android:pathData="M64.001,64m-60,0a60,60 0,1 1,119.999 0a60,60 0,1 1,-119.999 0"
|
||||
android:strokeWidth="6"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#007C1F"/>
|
||||
</group>
|
||||
<path
|
||||
android:pathData="M64,64m-26.25,0a26.25,26.25 0,1 1,52.5 0a26.25,26.25 0,1 1,-52.5 0"
|
||||
android:fillColor="#007C1F"
|
||||
/>
|
||||
<path
|
||||
android:pathData="M68.969,58.656C68.603,58.291 68.012,58.291 67.647,58.656L62.359,63.944L63.681,65.266L68.969,59.969C69.325,59.612 69.325,59.013 68.969,58.656ZM72.944,58.647L63.681,67.909L60.419,64.656C60.053,64.291 59.463,64.291 59.097,64.656C58.731,65.022 58.731,65.613 59.097,65.978L63.016,69.897C63.381,70.262 63.972,70.262 64.338,69.897L74.266,59.978C74.631,59.612 74.631,59.022 74.266,58.656L74.256,58.656C73.9,58.281 73.309,58.281 72.944,58.647ZM53.8,65.988L57.719,69.906C58.084,70.272 58.675,70.272 59.041,69.906L59.697,69.25L55.122,64.656C54.756,64.291 54.166,64.291 53.8,64.656C53.434,65.022 53.434,65.622 53.8,65.988Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="nonZero"/>
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
|
||||
<target android:name="scaleGroup"> *
|
||||
<aapt:attr name="android:animation">
|
||||
<set>
|
||||
<objectAnimator
|
||||
android:duration="1000"
|
||||
android:propertyName="scaleY"
|
||||
android:repeatCount="infinite"
|
||||
android:repeatMode="restart"
|
||||
android:valueFrom="0.5"
|
||||
android:valueTo="1.0" />
|
||||
<objectAnimator
|
||||
android:duration="1000"
|
||||
android:propertyName="scaleX"
|
||||
android:repeatCount="infinite"
|
||||
android:repeatMode="restart"
|
||||
android:valueFrom="0.5"
|
||||
android:valueTo="1.0" />
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
5
News-Android-App/src/main/res/drawable/fa_button.xml
Normal file
5
News-Android-App/src/main/res/drawable/fa_button.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true" android:drawable="@color/colorPrimaryDark"/>
|
||||
<item android:drawable="@color/colorPrimary"/>
|
||||
</selector>
|
5
News-Android-App/src/main/res/drawable/ic_done_all.xml
Normal file
5
News-Android-App/src/main/res/drawable/ic_done_all.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M18,7l-1.41,-1.41 -6.34,6.34 1.41,1.41L18,7zM22.24,5.59L11.66,16.17 7.48,12l-1.41,1.41L11.66,19l12,-12 -1.42,-1.41zM0.41,13.41L6,19l1.41,-1.41L1.83,12 0.41,13.41z"/>
|
||||
</vector>
|
18
News-Android-App/src/main/res/drawable/ic_fa_expand.xml
Normal file
18
News-Android-App/src/main/res/drawable/ic_fa_expand.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24.0001,24.0001m-21.0004,0a21.0004,21.0004 0,1 1,42.0009 0a21.0004,21.0004 0,1 1,-42.0009 0"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.25"/>
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:pathData="M 28 16 L 20 24 L 28 32 L 20 24 Z"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeWidth="4"/>
|
||||
</vector>
|
|
@ -0,0 +1,35 @@
|
|||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector
|
||||
android:name="vector"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24.0001,24.0001m-21.0004,0a21.0004,21.0004 0,1 1,42.0009 0a21.0004,21.0004 0,1 1,-42.0009 0"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.25"/>
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:pathData="M 28 16 L 20 24 L 28 32 L 20 24 Z"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeWidth="4"/>
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
<target android:name="path_1">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
android:propertyName="pathData"
|
||||
android:startOffset="1"
|
||||
android:duration="300"
|
||||
android:valueFrom="M 28 16 L 20 24 L 28 32 L 20 24 Z"
|
||||
android:valueTo="M 20 16 L 28 24 L 20 32 L 28 24 Z"
|
||||
android:valueType="pathType"
|
||||
android:interpolator="@android:interpolator/linear"/>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
9
News-Android-App/src/main/res/drawable/ic_fa_main_bg.xml
Normal file
9
News-Android-App/src/main/res/drawable/ic_fa_main_bg.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="56dp"
|
||||
android:height="56dp"
|
||||
android:viewportWidth="56"
|
||||
android:viewportHeight="56">
|
||||
<path
|
||||
android:pathData="M0,0L28,0C43.454,0 56,12.546 56,28C56,43.393 43.551,55.902 28.181,55.999L28,56L0,56L0,0Z"
|
||||
android:fillColor="#0082C9"/>
|
||||
</vector>
|
36
News-Android-App/src/main/res/drawable/ic_fa_shrink.xml
Normal file
36
News-Android-App/src/main/res/drawable/ic_fa_shrink.xml
Normal file
|
@ -0,0 +1,36 @@
|
|||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector
|
||||
android:name="vector"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24.0001,24.0001m-21.0004,0a21.0004,21.0004 0,1 1,42.0009 0a21.0004,21.0004 0,1 1,-42.0009 0"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.25"/>
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:pathData="M 20 16 L 28 24 L 20 32 L 28 24 Z"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeWidth="4"/>
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
<target android:name="path_1">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
android:propertyName="pathData"
|
||||
android:startOffset="1"
|
||||
android:duration="300"
|
||||
android:valueFrom="M 20 16 L 28 24 L 20 32 L 28 24 Z"
|
||||
android:valueTo="M 28 16 L 20 24 L 28 32 L 20 24 Z"
|
||||
android:valueType="pathType"
|
||||
android:interpolator="@android:interpolator/linear"/>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||
</vector>
|
|
@ -21,30 +21,46 @@
|
|||
for bottom toolbar, replace marginTop above with marginBottom
|
||||
android:layout_marginBottom="?attr/actionBarSize"
|
||||
-->
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/pager"
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".NewsDetailActivity" >
|
||||
|
||||
<!--
|
||||
This title strip will display the currently visible page title, as well as the page
|
||||
titles for adjacent pages.
|
||||
-->
|
||||
|
||||
<!--
|
||||
<android.support.v4.view.PagerTitleStrip
|
||||
android:id="@+id/pager_title_strip"
|
||||
>
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".NewsDetailActivity" >
|
||||
<!--
|
||||
This title strip will display the currently visible page title, as well as the page
|
||||
titles for adjacent pages.
|
||||
-->
|
||||
|
||||
<!--
|
||||
<android.support.v4.view.PagerTitleStrip
|
||||
android:id="@+id/pager_title_strip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:background="#33b5e5"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingTop="4dp"
|
||||
android:textColor="#fff" />
|
||||
-->
|
||||
|
||||
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
|
||||
<include
|
||||
android:id="@+id/fa_detail_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:background="#33b5e5"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingTop="4dp"
|
||||
android:textColor="#fff" />
|
||||
-->
|
||||
</androidx.viewpager.widget.ViewPager>
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginBottom="11dp"
|
||||
android:layout_marginEnd="11dp"
|
||||
layout="@layout/widget_fastactions_detailview" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/podcast_frame"
|
||||
|
@ -71,8 +87,7 @@
|
|||
android:theme="@style/ToolbarTheme"
|
||||
app:popupTheme="@style/ToolbarOptionMenuBackgroundTheme">
|
||||
</com.google.android.material.bottomappbar.BottomAppBar>
|
||||
-->
|
||||
|
||||
-->
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar_layout"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<FrameLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -37,6 +38,41 @@
|
|||
android:indeterminate="true" />
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_done_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:visibility="visible"
|
||||
android:translationX="-16dp"
|
||||
android:translationY="-16dp"
|
||||
app:tint="@android:color/white"
|
||||
app:fabSize="normal"
|
||||
app:backgroundTint="@color/colorPrimary"
|
||||
app:srcCompat="@drawable/ic_done_all"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/target_done_all"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:translationX="18dp"
|
||||
android:translationY="-64dp"
|
||||
android:layout_above="@id/fab_done_all"
|
||||
android:layout_alignParentEnd="true"
|
||||
app:srcCompat="@drawable/fa_all_read_target"
|
||||
android:visibility="invisible" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<!-- android:textIsSelectable="true" -->
|
||||
<!-- android:padding="16dp" -->
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/fa_bg"
|
||||
android:orientation="horizontal"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/fa_toggle"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="@color/transparent"
|
||||
app:srcCompat="@drawable/ic_fa_expand" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fa_collapse_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/fa_toggle"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/fa_mark_as_read"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@drawable/ic_check_box_outline_blank_white" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/fa_star"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@drawable/ic_action_star_border_dark" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/fa_share"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
app:srcCompat="@drawable/ic_share_white" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/fa_open_in_browser"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_toEndOf="@id/fa_collapse_layout"
|
||||
android:background="@drawable/fa_button"
|
||||
android:src="@drawable/ic_action_open_in_browser"
|
||||
android:translationZ="50dp" />
|
||||
</RelativeLayout>
|
|
@ -144,6 +144,7 @@
|
|||
<string name="pref_title_DisableHostnameVerification">Hostnamen-Nachweis deaktivieren</string>
|
||||
<string name="pref_title_NavigateWithVolumeButtons">Mit Lautstärketasten navigieren</string>
|
||||
<string name="pref_title_MarkAsReadWhileScrolling">Beim Bildlauf als gelesen markieren</string>
|
||||
<string name="pref_title_ShowFastActions">Schnellzugriffe aktivieren</string>
|
||||
<string name="pref_title_OpenInBrowserDirectly">Detailansicht überspringen und Artikel in Browser öffnen</string>
|
||||
|
||||
<string name="dialog_feature_not_available">Diese Funktion ist in dieser (Open-Source-)Version dieser App nicht verfügbar. Wenn Sie diese Funktion nutzen möchten, laden Sie bitte die App aus dem GitHub-Repository oder aus dem Google Play Store herunter.</string>
|
||||
|
|
|
@ -180,6 +180,7 @@
|
|||
<string name="pref_title_DisableHostnameVerification">Disable Hostname Verification</string>
|
||||
<string name="pref_title_NavigateWithVolumeButtons">Navigate with volume buttons</string>
|
||||
<string name="pref_title_MarkAsReadWhileScrolling">Mark as read while scrolling</string>
|
||||
<string name="pref_title_ShowFastActions">Activate fast access functions</string>
|
||||
<string name="pref_title_OpenInBrowserDirectly">Skip detailed view and open article in the browser</string>
|
||||
|
||||
<string name="dialog_feature_not_available">This feature is not available in this (open-source) version of this app. If you want to use this feature please download the app from the GitHub Repository or download the App from the Google Play Store.</string>
|
||||
|
|
|
@ -78,6 +78,11 @@
|
|||
android:title="@string/pref_title_MarkAsReadWhileScrolling"
|
||||
app:iconSpaceReserved="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="cb_ShowFastActions"
|
||||
android:title="@string/pref_title_ShowFastActions"
|
||||
app:iconSpaceReserved="false"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="cb_openInBrowserDirectly"
|
||||
android:title="@string/pref_title_OpenInBrowserDirectly"
|
||||
|
|
Loading…
Reference in a new issue