TabsFragment extracted
This commit is contained in:
parent
74073178bf
commit
51f783cea4
@ -106,6 +106,7 @@ import acr.browser.lightning.R;
|
||||
import acr.browser.lightning.app.BrowserApp;
|
||||
import acr.browser.lightning.bus.BookmarkEvents;
|
||||
import acr.browser.lightning.bus.BrowserEvents;
|
||||
import acr.browser.lightning.bus.TabEvents;
|
||||
import acr.browser.lightning.constant.BookmarkPage;
|
||||
import acr.browser.lightning.constant.Constants;
|
||||
import acr.browser.lightning.constant.HistoryPage;
|
||||
@ -113,6 +114,7 @@ import acr.browser.lightning.controller.BrowserController;
|
||||
import acr.browser.lightning.database.BookmarkManager;
|
||||
import acr.browser.lightning.database.HistoryDatabase;
|
||||
import acr.browser.lightning.dialog.BookmarksDialogBuilder;
|
||||
import acr.browser.lightning.fragment.TabsFragment;
|
||||
import acr.browser.lightning.object.ClickHandler;
|
||||
import acr.browser.lightning.object.SearchAdapter;
|
||||
import acr.browser.lightning.preference.PreferenceManager;
|
||||
@ -132,7 +134,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private FrameLayout mBrowserFrame;
|
||||
private FullscreenHolder mFullscreenContainer;
|
||||
private RecyclerView mDrawerListLeft;
|
||||
private ViewGroup mDrawerLeft, mDrawerRight, mUiLayout, mToolbarLayout;
|
||||
private RelativeLayout mSearchBar;
|
||||
|
||||
@ -144,7 +145,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
private View mCustomView;
|
||||
|
||||
// Adapter
|
||||
private LightningViewAdapter mTabAdapter;
|
||||
private SearchAdapter mSearchAdapter;
|
||||
|
||||
// Callback
|
||||
@ -247,7 +247,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
mUiLayout = (LinearLayout) findViewById(R.id.ui_layout);
|
||||
mProgressBar = (AnimatedProgressBar) findViewById(R.id.progress_view);
|
||||
setupFrameLayoutButton(R.id.new_tab_button, R.id.icon_plus);
|
||||
mDrawerLeft = (LinearLayout) findViewById(R.id.left_drawer);
|
||||
mDrawerLeft = (FrameLayout) findViewById(R.id.left_drawer);
|
||||
// Drawer stutters otherwise
|
||||
mDrawerLeft.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
@ -267,29 +267,19 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
|
||||
mHomepage = mPreferences.getHomepage();
|
||||
|
||||
RecyclerView horizontalListView = (RecyclerView) findViewById(R.id.twv_list);
|
||||
|
||||
|
||||
final TabsFragment tabsFragment = new TabsFragment();
|
||||
final int containerId = mShowTabsInDrawer ? R.id.left_drawer : R.id.tabs_toolbar_container;
|
||||
final Bundle arguments = new Bundle();
|
||||
arguments.putBoolean(TabsFragment.VERTICAL_MODE, mShowTabsInDrawer);
|
||||
tabsFragment.setArguments(arguments);
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.add(containerId, tabsFragment)
|
||||
.commit();
|
||||
if (mShowTabsInDrawer) {
|
||||
mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item, tabsManager.getTabsList());
|
||||
mDrawerListLeft = (RecyclerView) findViewById(R.id.left_drawer_list);
|
||||
mDrawerListLeft.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
|
||||
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
|
||||
mDrawerListLeft.setLayoutManager(layoutManager);
|
||||
mDrawerListLeft.setHasFixedSize(true);
|
||||
mToolbarLayout.removeView(horizontalListView);
|
||||
} else {
|
||||
mTabAdapter = new LightningViewAdapter(this, R.layout.tab_list_item_horizontal, tabsManager.getTabsList());
|
||||
mDrawerListLeft = horizontalListView;
|
||||
mDrawerListLeft.setOverScrollMode(View.OVER_SCROLL_NEVER);
|
||||
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mDrawerLeft);
|
||||
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
|
||||
mDrawerListLeft.setLayoutManager(layoutManager);
|
||||
mDrawerListLeft.setHasFixedSize(true);
|
||||
mToolbarLayout.removeView(findViewById(R.id.tabs_toolbar_container));
|
||||
}
|
||||
|
||||
mDrawerListLeft.setAdapter(mTabAdapter);
|
||||
|
||||
mHistoryDatabase = HistoryDatabase.getInstance();
|
||||
|
||||
if (actionBar == null)
|
||||
@ -872,56 +862,29 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
builder.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* The click listener for ListView in the navigation drawer
|
||||
*/
|
||||
private class DrawerItemClickListener implements OnClickListener {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final LightningView currentTab = tabsManager.getCurrentTab();
|
||||
final int position = mDrawerListLeft.getChildAdapterPosition(v);
|
||||
final LightningView tab = tabsManager.getTabAtPosition(position);
|
||||
if (tab != null && currentTab != tab) {
|
||||
mIsNewIntent = false;
|
||||
showTab(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* long click listener for Navigation Drawer
|
||||
*/
|
||||
private class DrawerItemLongClickListener implements OnLongClickListener {
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
int position = mDrawerListLeft.getChildAdapterPosition(v);
|
||||
showCloseDialog(position);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* displays the WebView contained in the LightningView Also handles the
|
||||
* removal of previous views
|
||||
*
|
||||
* @param newView the LightningView to show
|
||||
* @param position the poition of the tab to display
|
||||
*/
|
||||
private synchronized void showTab(LightningView newView) {
|
||||
private synchronized void showTab(final int position) {
|
||||
final LightningView currentView = tabsManager.getCurrentTab();
|
||||
final LightningView newView = tabsManager.switchToTab(position);
|
||||
|
||||
// Set the background color so the color mode color doesn't show through
|
||||
mBrowserFrame.setBackgroundColor(mBackgroundColor);
|
||||
if (newView == null) {
|
||||
if (newView == null || currentView == newView) {
|
||||
return;
|
||||
}
|
||||
mIsNewIntent = false;
|
||||
|
||||
final float translation = mToolbarLayout.getTranslationY();
|
||||
mBrowserFrame.removeAllViews();
|
||||
if (currentView != null) {
|
||||
currentView.setForegroundTab(false);
|
||||
currentView.onPause();
|
||||
}
|
||||
tabsManager.setCurrentTab(newView);
|
||||
final WebView currentWebView = currentView.getWebView();
|
||||
newView.setForegroundTab(true);
|
||||
if (currentWebView != null) {
|
||||
@ -1047,15 +1010,17 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
mIdGenerator++;
|
||||
|
||||
if (show) {
|
||||
showTab(startingTab);
|
||||
showTab(tabsManager.size() - 1);
|
||||
}
|
||||
updateTabs();
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDrawerListLeft.smoothScrollToPosition(tabsManager.size() - 1);
|
||||
}
|
||||
}, 300);
|
||||
|
||||
// TODO Restore this
|
||||
// new Handler().postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// mDrawerListLeft.smoothScrollToPosition(tabsManager.size() - 1);
|
||||
// }
|
||||
// }, 300);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1082,14 +1047,14 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
}
|
||||
if (current > position) {
|
||||
tabsManager.deleteTab(position);
|
||||
showTab(tabsManager.getTabAtPosition(current - 1));
|
||||
showTab(current - 1);
|
||||
updateTabs();
|
||||
tabToDelete.onDestroy();
|
||||
} else if (tabsManager.size() > position + 1) {
|
||||
if (current == position) {
|
||||
showTab(tabsManager.getTabAtPosition(position + 1));
|
||||
showTab(position + 1);
|
||||
tabsManager.deleteTab(position);
|
||||
showTab(tabsManager.getTabAtPosition(position));
|
||||
showTab(position);
|
||||
updateTabs();
|
||||
} else {
|
||||
tabsManager.deleteTab(position);
|
||||
@ -1098,9 +1063,9 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
tabToDelete.onDestroy();
|
||||
} else if (tabsManager.size() > 1) {
|
||||
if (current == position) {
|
||||
showTab(tabsManager.getTabAtPosition(position - 1));
|
||||
showTab(position - 1);
|
||||
tabsManager.deleteTab(position);
|
||||
showTab(tabsManager.getTabAtPosition(position - 1));
|
||||
showTab(position - 1);
|
||||
updateTabs();
|
||||
} else {
|
||||
tabsManager.deleteTab(position);
|
||||
@ -1115,11 +1080,11 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
performExitCleanUp();
|
||||
tabToDelete.pauseTimers();
|
||||
tabToDelete.onDestroy();
|
||||
mTabAdapter.notifyDataSetChanged();
|
||||
eventBus.post(new BrowserEvents.TabsChanged());
|
||||
finish();
|
||||
}
|
||||
}
|
||||
mTabAdapter.notifyDataSetChanged();
|
||||
eventBus.post(new BrowserEvents.TabsChanged());
|
||||
|
||||
if (mIsNewIntent && isShown) {
|
||||
mIsNewIntent = false;
|
||||
@ -1167,7 +1132,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
mBrowserFrame.setBackgroundColor(mBackgroundColor);
|
||||
performExitCleanUp();
|
||||
tabsManager.shutdown();
|
||||
mTabAdapter.notifyDataSetChanged();
|
||||
eventBus.post(new BrowserEvents.TabsChanged());
|
||||
finish();
|
||||
}
|
||||
|
||||
@ -1293,157 +1258,6 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
}
|
||||
}
|
||||
|
||||
public class LightningViewAdapter extends RecyclerView.Adapter<LightningViewAdapter.LightningViewHolder> {
|
||||
|
||||
private final Context context;
|
||||
private final int layoutResourceId;
|
||||
private List<LightningView> data = null;
|
||||
private final CloseTabListener mExitListener;
|
||||
private final Drawable mBackgroundTabDrawable;
|
||||
private final Drawable mForegroundTabDrawable;
|
||||
private final Bitmap mForegroundTabBitmap;
|
||||
private final DrawerItemClickListener mClickListener;
|
||||
private final DrawerItemLongClickListener mLongClickListener;
|
||||
private ColorMatrix mColorMatrix;
|
||||
private Paint mPaint;
|
||||
private ColorFilter mFilter;
|
||||
private static final float DESATURATED = 0.5f;
|
||||
|
||||
public LightningViewAdapter(Context context, int layoutResourceId, List<LightningView> data) {
|
||||
this.layoutResourceId = layoutResourceId;
|
||||
this.context = context;
|
||||
this.data = data;
|
||||
this.mExitListener = new CloseTabListener();
|
||||
this.mClickListener = new DrawerItemClickListener();
|
||||
this.mLongClickListener = new DrawerItemLongClickListener();
|
||||
|
||||
if (mShowTabsInDrawer) {
|
||||
mBackgroundTabDrawable = null;
|
||||
mForegroundTabBitmap = null;
|
||||
mForegroundTabDrawable = ThemeUtils.getSelectedBackground(context, mDarkTheme);
|
||||
} else {
|
||||
int backgroundColor = Utils.mixTwoColors(ThemeUtils.getPrimaryColor(mActivity), Color.BLACK, 0.75f);
|
||||
Bitmap backgroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888);
|
||||
Utils.drawTrapezoid(new Canvas(backgroundTabBitmap), backgroundColor, true);
|
||||
mBackgroundTabDrawable = new BitmapDrawable(getResources(), backgroundTabBitmap);
|
||||
|
||||
int foregroundColor = ThemeUtils.getPrimaryColor(context);
|
||||
mForegroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888);
|
||||
Utils.drawTrapezoid(new Canvas(mForegroundTabBitmap), foregroundColor, false);
|
||||
mForegroundTabDrawable = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LightningViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
||||
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
|
||||
View view = inflater.inflate(layoutResourceId, viewGroup, false);
|
||||
return new LightningViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final LightningViewHolder holder, int position) {
|
||||
holder.exitButton.setTag(position);
|
||||
holder.exitButton.setOnClickListener(mExitListener);
|
||||
holder.layout.setOnClickListener(mClickListener);
|
||||
holder.layout.setOnLongClickListener(mLongClickListener);
|
||||
|
||||
ViewCompat.jumpDrawablesToCurrentState(holder.exitButton);
|
||||
|
||||
LightningView web = data.get(position);
|
||||
holder.txtTitle.setText(web.getTitle());
|
||||
|
||||
final Bitmap favicon = web.getFavicon();
|
||||
if (web.isForegroundTab()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
holder.txtTitle.setTextAppearance(R.style.boldText);
|
||||
} else {
|
||||
holder.txtTitle.setTextAppearance(context, R.style.boldText);
|
||||
}
|
||||
Drawable foregroundDrawable;
|
||||
if (!mShowTabsInDrawer) {
|
||||
foregroundDrawable = new BitmapDrawable(getResources(), mForegroundTabBitmap);
|
||||
if (!isIncognito() && mColorMode) {
|
||||
foregroundDrawable.setColorFilter(mCurrentUiColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
} else {
|
||||
foregroundDrawable = mForegroundTabDrawable;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
holder.layout.setBackground(foregroundDrawable);
|
||||
} else {
|
||||
holder.layout.setBackgroundDrawable(foregroundDrawable);
|
||||
}
|
||||
if (!isIncognito() && mColorMode) {
|
||||
changeToolbarBackground(favicon, foregroundDrawable);
|
||||
}
|
||||
holder.favicon.setImageBitmap(favicon);
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
holder.txtTitle.setTextAppearance(R.style.normalText);
|
||||
} else {
|
||||
holder.txtTitle.setTextAppearance(context, R.style.normalText);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
holder.layout.setBackground(mBackgroundTabDrawable);
|
||||
} else {
|
||||
holder.layout.setBackgroundDrawable(mBackgroundTabDrawable);
|
||||
}
|
||||
holder.favicon.setImageBitmap(getDesaturatedBitmap(favicon));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return (data != null) ? data.size() : 0;
|
||||
}
|
||||
|
||||
public Bitmap getDesaturatedBitmap(Bitmap favicon) {
|
||||
Bitmap grayscaleBitmap = Bitmap.createBitmap(favicon.getWidth(),
|
||||
favicon.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas c = new Canvas(grayscaleBitmap);
|
||||
if (mColorMatrix == null || mFilter == null || mPaint == null) {
|
||||
mPaint = new Paint();
|
||||
mColorMatrix = new ColorMatrix();
|
||||
mColorMatrix.setSaturation(DESATURATED);
|
||||
mFilter = new ColorMatrixColorFilter(mColorMatrix);
|
||||
mPaint.setColorFilter(mFilter);
|
||||
}
|
||||
|
||||
c.drawBitmap(favicon, 0, 0, mPaint);
|
||||
return grayscaleBitmap;
|
||||
}
|
||||
|
||||
public class LightningViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public LightningViewHolder(View view) {
|
||||
super(view);
|
||||
txtTitle = (TextView) view.findViewById(R.id.textTab);
|
||||
favicon = (ImageView) view.findViewById(R.id.faviconTab);
|
||||
exit = (ImageView) view.findViewById(R.id.deleteButton);
|
||||
layout = (LinearLayout) view.findViewById(R.id.tab_item_background);
|
||||
exitButton = (FrameLayout) view.findViewById(R.id.deleteAction);
|
||||
exit.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
final TextView txtTitle;
|
||||
final ImageView favicon;
|
||||
final ImageView exit;
|
||||
final FrameLayout exitButton;
|
||||
final LinearLayout layout;
|
||||
}
|
||||
}
|
||||
|
||||
private class CloseTabListener implements OnClickListener {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
deleteTab((int) v.getTag());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates the color of the toolbar from one color to another. Optionally animates
|
||||
* the color of the tab background, for use when the tabs are displayed on the top
|
||||
@ -1684,7 +1498,7 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
|
||||
@Override
|
||||
public void updateTabs() {
|
||||
mTabAdapter.notifyDataSetChanged();
|
||||
eventBus.post(new BrowserEvents.TabsChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2482,5 +2296,33 @@ public abstract class BrowserActivity extends ThemableBrowserActivity implements
|
||||
public void closeBookmarks(final BookmarkEvents.CloseBookmarks event) {
|
||||
mDrawerLayout.closeDrawer(mDrawerRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user wants to close a tab
|
||||
*
|
||||
* @param event contains the position inside the tabs adapter
|
||||
*/
|
||||
@Subscribe
|
||||
public void closeTab(final TabEvents.CloseTab event) {
|
||||
deleteTab(event.position);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user clicked on a tab, let's show it
|
||||
*
|
||||
* @param event contains the tab position in the tabs adapter
|
||||
*/
|
||||
public void showTab(final TabEvents.ShowTab event) {
|
||||
BrowserActivity.this.showTab(event.position);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user long pressed on a tab, ask him if he want to close the tab
|
||||
*
|
||||
* @param event contains the tab position in the tabs adapter
|
||||
*/
|
||||
public void showCloseDialog(final TabEvents.ShowCloseDialog event) {
|
||||
BrowserActivity.this.showCloseDialog(event.position);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ public class TabsManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO We should remove also this
|
||||
* TODO We should remove also this, but probably not
|
||||
* @return
|
||||
*/
|
||||
public LightningView getCurrentTab() {
|
||||
@ -189,9 +189,27 @@ public class TabsManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO We should remove also this
|
||||
* Switch the current tab to the one at the given position. It returns the selected. After this
|
||||
* call {@link TabsManager#getCurrentTab()} return the same reference returned by this method if
|
||||
* position is valid.
|
||||
*
|
||||
* @return the selected tab or null if position is out of tabs range
|
||||
*/
|
||||
public void setCurrentTab(final LightningView tab) {
|
||||
mCurrentTab = tab;
|
||||
@Nullable
|
||||
public LightningView switchToTab(final int position) {
|
||||
if (position < 0 || position >= mWebViewList.size()) {
|
||||
return null;
|
||||
} else {
|
||||
final LightningView tab = mWebViewList.get(position);
|
||||
mCurrentTab = tab;
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * TODO We should remove also this
|
||||
// */
|
||||
// public void setCurrentTab(final LightningView tab) {
|
||||
// mCurrentTab = tab;
|
||||
// }
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import acr.browser.lightning.constant.BookmarkPage;
|
||||
import acr.browser.lightning.dialog.BookmarksDialogBuilder;
|
||||
import acr.browser.lightning.fragment.BookmarkSettingsFragment;
|
||||
import acr.browser.lightning.fragment.BookmarksFragment;
|
||||
import acr.browser.lightning.fragment.TabsFragment;
|
||||
import acr.browser.lightning.object.SearchAdapter;
|
||||
import dagger.Component;
|
||||
|
||||
@ -28,4 +29,6 @@ public interface AppComponent {
|
||||
void inject(BookmarksDialogBuilder builder);
|
||||
|
||||
void inject(BookmarkPage bookmarkPage);
|
||||
|
||||
void inject(TabsFragment fragment);
|
||||
}
|
||||
|
@ -41,4 +41,10 @@ public final class BrowserEvents {
|
||||
*/
|
||||
public static class UserPressedBack {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that the user closed or opened a tab
|
||||
*/
|
||||
public static class TabsChanged {
|
||||
}
|
||||
}
|
||||
|
49
app/src/main/java/acr/browser/lightning/bus/TabEvents.java
Normal file
49
app/src/main/java/acr/browser/lightning/bus/TabEvents.java
Normal file
@ -0,0 +1,49 @@
|
||||
package acr.browser.lightning.bus;
|
||||
|
||||
/**
|
||||
* @author Stefano Pacifici
|
||||
* @date 2015/09/14
|
||||
*/
|
||||
public final class TabEvents {
|
||||
|
||||
private TabEvents() {
|
||||
// No instances
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user click on the
|
||||
* tab exit button
|
||||
*/
|
||||
public static class CloseTab {
|
||||
public final int position;
|
||||
|
||||
public CloseTab(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user click on the
|
||||
* tab itself.
|
||||
*/
|
||||
public static class ShowTab {
|
||||
public final int position;
|
||||
|
||||
public ShowTab(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sended by {@link acr.browser.lightning.fragment.TabsFragment} when the user long press on the
|
||||
* tab itself.
|
||||
*/
|
||||
public static class ShowCloseDialog {
|
||||
public final int position;
|
||||
|
||||
public ShowCloseDialog(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,281 @@
|
||||
package acr.browser.lightning.fragment;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.RecyclerView.LayoutManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import acr.browser.lightning.R;
|
||||
import acr.browser.lightning.activity.TabsManager;
|
||||
import acr.browser.lightning.app.BrowserApp;
|
||||
import acr.browser.lightning.bus.BrowserEvents;
|
||||
import acr.browser.lightning.bus.TabEvents;
|
||||
import acr.browser.lightning.utils.ThemeUtils;
|
||||
import acr.browser.lightning.utils.Utils;
|
||||
import acr.browser.lightning.view.LightningView;
|
||||
|
||||
/**
|
||||
* @author Stefano Pacifici based on Anthony C. Restaino's code
|
||||
* @date 2015/09/14
|
||||
*/
|
||||
public class TabsFragment extends Fragment {
|
||||
|
||||
private static final String TAG = TabsFragment.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Arguments boolean to tell the fragment it is displayed in the drawner or on the tab strip
|
||||
* If true, the fragment is in the left drawner in the strip otherwise.
|
||||
*/
|
||||
public static final String VERTICAL_MODE = TAG + ".VERTICAL_MODE";
|
||||
|
||||
private boolean mDarkTheme = false; // TODO Only temporary
|
||||
private int mIconColor = 0; // TODO Only temporary
|
||||
private boolean mColorMode = true; // TODO Only temporary
|
||||
private boolean isIncognito = false; // TODO Only temporary
|
||||
private int mCurrentUiColor = 0; // TODO Only temporary
|
||||
|
||||
private RecyclerView mRecyclerView;
|
||||
private LightningViewAdapter mTabsAdapter;
|
||||
|
||||
@Inject
|
||||
TabsManager tabsManager;
|
||||
|
||||
@Inject
|
||||
Bus bus;
|
||||
|
||||
public TabsFragment() {
|
||||
BrowserApp.getAppComponent().inject(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
final Bundle arguments = getArguments();
|
||||
final boolean vertical = arguments.getBoolean(VERTICAL_MODE, true);
|
||||
final View view;
|
||||
final LayoutManager layoutManager;
|
||||
if (vertical) {
|
||||
view = inflater.inflate(R.layout.tab_drawer, container, false);
|
||||
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
|
||||
} else {
|
||||
view = inflater.inflate(R.layout.tab_strip, container, false);
|
||||
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
|
||||
}
|
||||
mRecyclerView = (RecyclerView) view.findViewById(R.id.tabs_list);
|
||||
mRecyclerView.setLayoutManager(layoutManager);
|
||||
mTabsAdapter = new LightningViewAdapter(vertical);
|
||||
mRecyclerView.setAdapter(mTabsAdapter);
|
||||
mRecyclerView.setHasFixedSize(true);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mRecyclerView = null;
|
||||
mTabsAdapter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
bus.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
bus.unregister(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void tabsChanged(final BrowserEvents.TabsChanged event) {
|
||||
if (mTabsAdapter != null) {
|
||||
mTabsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public class LightningViewAdapter extends RecyclerView.Adapter<LightningViewAdapter.LightningViewHolder> {
|
||||
|
||||
private final int layoutResourceId;
|
||||
private final Drawable mBackgroundTabDrawable;
|
||||
private final Drawable mForegroundTabDrawable;
|
||||
private final Bitmap mForegroundTabBitmap;
|
||||
private ColorMatrix mColorMatrix;
|
||||
private Paint mPaint;
|
||||
private ColorFilter mFilter;
|
||||
private static final float DESATURATED = 0.5f;
|
||||
|
||||
private final boolean vertical;
|
||||
|
||||
public LightningViewAdapter(final boolean vertical) {
|
||||
this.layoutResourceId = vertical ? R.layout.tab_list_item : R.layout.tab_list_item_horizontal;
|
||||
this.vertical = vertical;
|
||||
|
||||
if (vertical) {
|
||||
mBackgroundTabDrawable = null;
|
||||
mForegroundTabBitmap = null;
|
||||
mForegroundTabDrawable = ThemeUtils.getSelectedBackground(getContext(), mDarkTheme);
|
||||
} else {
|
||||
int backgroundColor = Utils.mixTwoColors(ThemeUtils.getPrimaryColor(getContext()), Color.BLACK, 0.75f);
|
||||
Bitmap backgroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888);
|
||||
Utils.drawTrapezoid(new Canvas(backgroundTabBitmap), backgroundColor, true);
|
||||
mBackgroundTabDrawable = new BitmapDrawable(getResources(), backgroundTabBitmap);
|
||||
|
||||
int foregroundColor = ThemeUtils.getPrimaryColor(getContext());
|
||||
mForegroundTabBitmap = Bitmap.createBitmap(Utils.dpToPx(175), Utils.dpToPx(30), Bitmap.Config.ARGB_8888);
|
||||
Utils.drawTrapezoid(new Canvas(mForegroundTabBitmap), foregroundColor, false);
|
||||
mForegroundTabDrawable = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LightningViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
||||
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
|
||||
View view = inflater.inflate(layoutResourceId, viewGroup, false);
|
||||
return new LightningViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final LightningViewHolder holder, int position) {
|
||||
holder.exitButton.setTag(position);
|
||||
|
||||
ViewCompat.jumpDrawablesToCurrentState(holder.exitButton);
|
||||
|
||||
LightningView web = tabsManager.getTabAtPosition(position);
|
||||
holder.txtTitle.setText(web.getTitle());
|
||||
|
||||
final Bitmap favicon = web.getFavicon();
|
||||
if (web.isForegroundTab()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
holder.txtTitle.setTextAppearance(R.style.boldText);
|
||||
} else {
|
||||
holder.txtTitle.setTextAppearance(getContext(), R.style.boldText);
|
||||
}
|
||||
Drawable foregroundDrawable;
|
||||
if (!vertical) {
|
||||
foregroundDrawable = new BitmapDrawable(getResources(), mForegroundTabBitmap);
|
||||
if (!isIncognito && mColorMode) {
|
||||
foregroundDrawable.setColorFilter(mCurrentUiColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
} else {
|
||||
foregroundDrawable = mForegroundTabDrawable;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
holder.layout.setBackground(foregroundDrawable);
|
||||
} else {
|
||||
holder.layout.setBackgroundDrawable(foregroundDrawable);
|
||||
}
|
||||
if (!isIncognito && mColorMode) {
|
||||
// TODO Restore this
|
||||
// changeToolbarBackground(favicon, foregroundDrawable);
|
||||
}
|
||||
holder.favicon.setImageBitmap(favicon);
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
holder.txtTitle.setTextAppearance(R.style.normalText);
|
||||
} else {
|
||||
holder.txtTitle.setTextAppearance(getContext(), R.style.normalText);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
holder.layout.setBackground(mBackgroundTabDrawable);
|
||||
} else {
|
||||
holder.layout.setBackgroundDrawable(mBackgroundTabDrawable);
|
||||
}
|
||||
holder.favicon.setImageBitmap(getDesaturatedBitmap(favicon));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return tabsManager.size();
|
||||
}
|
||||
|
||||
public Bitmap getDesaturatedBitmap(Bitmap favicon) {
|
||||
Bitmap grayscaleBitmap = Bitmap.createBitmap(favicon.getWidth(),
|
||||
favicon.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas c = new Canvas(grayscaleBitmap);
|
||||
if (mColorMatrix == null || mFilter == null || mPaint == null) {
|
||||
mPaint = new Paint();
|
||||
mColorMatrix = new ColorMatrix();
|
||||
mColorMatrix.setSaturation(DESATURATED);
|
||||
mFilter = new ColorMatrixColorFilter(mColorMatrix);
|
||||
mPaint.setColorFilter(mFilter);
|
||||
}
|
||||
|
||||
c.drawBitmap(favicon, 0, 0, mPaint);
|
||||
return grayscaleBitmap;
|
||||
}
|
||||
|
||||
public class LightningViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
public LightningViewHolder(View view) {
|
||||
super(view);
|
||||
txtTitle = (TextView) view.findViewById(R.id.textTab);
|
||||
favicon = (ImageView) view.findViewById(R.id.faviconTab);
|
||||
exit = (ImageView) view.findViewById(R.id.deleteButton);
|
||||
layout = (LinearLayout) view.findViewById(R.id.tab_item_background);
|
||||
exitButton = (FrameLayout) view.findViewById(R.id.deleteAction);
|
||||
exit.setColorFilter(mIconColor, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
exitButton.setOnClickListener(this);
|
||||
layout.setOnClickListener(this);
|
||||
layout.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
final TextView txtTitle;
|
||||
final ImageView favicon;
|
||||
final ImageView exit;
|
||||
final FrameLayout exitButton;
|
||||
final LinearLayout layout;
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == exitButton) {
|
||||
// Close tab
|
||||
bus.post(new TabEvents.CloseTab(getAdapterPosition()));
|
||||
}
|
||||
if (v == layout) {
|
||||
bus.post(new TabEvents.ShowTab(getAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
// Show close dialog
|
||||
bus.post(new TabEvents.ShowCloseDialog(getAdapterPosition()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,12 @@
|
||||
<include layout="@layout/search_interface" />
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/tab_drawer" />
|
||||
<FrameLayout
|
||||
android:layout_width="@dimen/navigation_width"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/drawerBackground"
|
||||
android:id="@+id/left_drawer"
|
||||
android:fitsSystemWindows="true" />
|
||||
|
||||
<FrameLayout
|
||||
android:weightSum="1"
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/left_drawer"
|
||||
android:layout_width="@dimen/navigation_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
@ -45,12 +44,13 @@
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/left_drawer_list"
|
||||
android:id="@+id/tabs_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="0dp" />
|
||||
android:dividerHeight="0dp"
|
||||
android:overScrollMode="ifContentScrolls" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
9
app/src/main/res/layout/tab_strip.xml
Normal file
9
app/src/main/res/layout/tab_strip.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="@color/black"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:id="@+id/tabs_list" />
|
||||
|
@ -8,13 +8,10 @@
|
||||
android:elevation="2dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/twv_list"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="@color/black"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none" />
|
||||
android:id="@+id/tabs_toolbar_container"/>
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
|
Loading…
x
Reference in New Issue
Block a user