package it.neokree.materialnavigationdrawer; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.Toolbar; import android.util.TypedValue; import android.view.Display; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import it.neokree.materialnavigationdrawer.util.MaterialDrawerLayout; import it.neokree.materialnavigationdrawer.util.Utils; import uk.co.chrisjenx.calligraphy.CalligraphyConfig; import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper; /** * Activity that implements ActionBarActivity with a Navigation Drawer with Material Design style * * @author created by neokree */ @SuppressLint("InflateParams") public abstract class MaterialNavigationDrawer<Fragment> extends ActionBarActivity implements MaterialSectionListener,MaterialAccount.OnAccountDataLoaded { public static final int BOTTOM_SECTION_START = 100; private static final int USER_CHANGE_TRANSITION = 500; public static final int BACKPATTERN_BACK_ANYWHERE = 0; public static final int BACKPATTERN_BACK_TO_FIRST = 1; public static final int BACKPATTERN_CUSTOM = 2; private static final int DRAWERHEADER_ACCOUNTS = 0; private static final int DRAWERHEADER_IMAGE = 1; private static final int DRAWERHEADER_CUSTOM = 2; private static final int DRAWERHEADER_NO_HEADER = 3; private static final String STATE_SECTION = "section"; private static final String STATE_ACCOUNT = "account"; private MaterialDrawerLayout layout; private ActionBar actionBar; private ActionBarDrawerToggle pulsante; private ImageView statusBar; private Toolbar toolbar; private RelativeLayout content; private RelativeLayout drawer; private ImageView userphoto; private ImageView userSecondPhoto; private ImageView userThirdPhoto; private ImageView usercover; private ImageView usercoverSwitcher; private TextView username; private TextView usermail; private LinearLayout customDrawerHeader; private LinearLayout sections; private LinearLayout bottomSections; private List<MaterialSection> sectionList; private List<MaterialSection> bottomSectionList; private List<MaterialAccount> accountManager; private MaterialSection currentSection; private MaterialAccount currentAccount; private CharSequence title; private float density; private int primaryColor; private int primaryDarkColor; private boolean drawerTouchLocked = false; private boolean slidingDrawerEffect = false; private boolean multiPaneSupport = false; private boolean rippleSupport; private boolean kitkatTraslucentStatusbar = false; private static boolean learningPattern = true; private Resources resources; private int backPattern = BACKPATTERN_BACK_ANYWHERE; private int drawerHeaderType; private View.OnClickListener currentAccountListener = new View.OnClickListener() { @Override public void onClick(View v) { if(!drawerTouchLocked) { // enter into account properties if (accountListener != null) { accountListener.onAccountOpening(currentAccount); } // close drawer if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); } } }; private View.OnClickListener secondAccountListener = new View.OnClickListener() { @Override public void onClick(View v) { if(!drawerTouchLocked) { // account change MaterialAccount account = findAccountNumber(MaterialAccount.SECOND_ACCOUNT); if (account != null) { if (accountListener != null) accountListener.onChangeAccount(account); switchAccounts(account); } else {// if there is no second account user clicked for open it accountListener.onAccountOpening(currentAccount); if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); } } } }; private View.OnClickListener thirdAccountListener = new View.OnClickListener() { @Override public void onClick(View v) { if(!drawerTouchLocked) { // account change MaterialAccount account = findAccountNumber(MaterialAccount.THIRD_ACCOUNT); if (account != null) { if (accountListener != null) accountListener.onChangeAccount(account); switchAccounts(account); } else {// if there is no second account user clicked for open it accountListener.onAccountOpening(currentAccount); if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); } } } }; private MaterialAccountListener accountListener; private DrawerLayout.DrawerListener drawerListener; @Override protected void attachBaseContext(Context newBase) { // init the Calligraphy library super.attachBaseContext(new CalligraphyContextWrapper(newBase,R.attr.materialFontPath)); } @Override /** * Do not Override this method!!! <br> * Use init() instead */ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); CalligraphyConfig.initDefault("fonts/Roboto-Regular.ttf", R.attr.materialFontPath); Resources.Theme theme = this.getTheme(); TypedValue typedValue = new TypedValue(); theme.resolveAttribute(R.attr.drawerType,typedValue,true); drawerHeaderType = typedValue.data; theme.resolveAttribute(R.attr.rippleBackport,typedValue,false); rippleSupport = typedValue.data != 0; if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) setContentView(R.layout.activity_material_navigation_drawer); else setContentView(R.layout.activity_material_navigation_drawer_customheader); // init toolbar & status bar statusBar = (ImageView) findViewById(R.id.statusBar); toolbar = (Toolbar) findViewById(R.id.toolbar); // init drawer components layout = (MaterialDrawerLayout) this.findViewById(R.id.drawer_layout); content = (RelativeLayout) this.findViewById(R.id.content); drawer = (RelativeLayout) this.findViewById(R.id.drawer); if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) { username = (TextView) this.findViewById(R.id.user_nome); usermail = (TextView) this.findViewById(R.id.user_email); userphoto = (ImageView) this.findViewById(R.id.user_photo); userSecondPhoto = (ImageView) this.findViewById(R.id.user_photo_2); userThirdPhoto = (ImageView) this.findViewById(R.id.user_photo_3); usercover = (ImageView) this.findViewById(R.id.user_cover); usercoverSwitcher = (ImageView) this.findViewById(R.id.user_cover_switcher); } else customDrawerHeader = (LinearLayout) this.findViewById(R.id.drawer_header); sections = (LinearLayout) this.findViewById(R.id.sections); bottomSections = (LinearLayout) this.findViewById(R.id.bottom_sections); // init lists sectionList = new LinkedList<>(); bottomSectionList = new LinkedList<>(); accountManager = new LinkedList<>(); // init listeners if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) { userphoto.setOnClickListener(currentAccountListener); usercover.setOnClickListener(currentAccountListener); userSecondPhoto.setOnClickListener(secondAccountListener); userThirdPhoto.setOnClickListener(thirdAccountListener); } //get resources and density resources = this.getResources(); density = resources.getDisplayMetrics().density; // set the right drawer width DrawerLayout.LayoutParams drawerParams = (android.support.v4.widget.DrawerLayout.LayoutParams) drawer.getLayoutParams(); drawerParams.width = Utils.getDrawerWidth(resources); drawer.setLayoutParams(drawerParams); // get primary color theme.resolveAttribute(R.attr.colorPrimary, typedValue, true); primaryColor = typedValue.data; theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true); primaryDarkColor = typedValue.data; // if device is kitkat if(Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) { TypedArray windowTraslucentAttribute = theme.obtainStyledAttributes(new int[]{android.R.attr.windowTranslucentStatus}); kitkatTraslucentStatusbar = windowTraslucentAttribute.getBoolean(0, false); if(kitkatTraslucentStatusbar) { Window window = this.getWindow(); window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); RelativeLayout.LayoutParams statusParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resources.getDimensionPixelSize(R.dimen.traslucentStatusMargin)); statusBar.setLayoutParams(statusParams); statusBar.setImageDrawable(new ColorDrawable(darkenColor(primaryColor))); if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) { RelativeLayout.LayoutParams photoParams = (RelativeLayout.LayoutParams) userphoto.getLayoutParams(); photoParams.setMargins((int) (16 * density), resources.getDimensionPixelSize(R.dimen.traslucentPhotoMarginTop), 0, 0); userphoto.setLayoutParams(photoParams); } } } // INIT ACTION BAR this.setSupportActionBar(toolbar); actionBar = getSupportActionBar(); // DEVELOPER CALL TO INIT init(savedInstanceState); if(sectionList.size() == 0) { throw new RuntimeException("You must add at least one Section to top list."); } Configuration configuration = resources.getConfiguration(); if(deviceSupportMultiPane()) { // se il multipane e' attivo, si e' in landscape e si e' un tablet allora si passa in multipane mode layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN,drawer); DrawerLayout.LayoutParams params = new DrawerLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); params.setMargins((int) (320 * density),0,0,0); content.setLayoutParams(params); layout.setScrimColor(Color.TRANSPARENT); layout.openDrawer(drawer); layout.requestDisallowInterceptTouchEvent(true); } else { // se non si sta lavorando in multiPane allora si inserisce il pulsante per aprire/chiudere actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true); pulsante = new ActionBarDrawerToggle(this,layout,toolbar,R.string.nothing,R.string.nothing) { public void onDrawerClosed(View view) { invalidateOptionsMenu(); // termina il comando // abilita il touch del drawer drawerTouchLocked = false; setSectionsTouch(true); if(drawerListener != null) drawerListener.onDrawerClosed(view); } public void onDrawerOpened(View drawerView) { invalidateOptionsMenu(); // termina il comando if(drawerListener != null) drawerListener.onDrawerOpened(drawerView); } @Override public void onDrawerSlide(View drawerView, float slideOffset) { // if user wants the sliding arrow it compare if(slidingDrawerEffect) super.onDrawerSlide(drawerView, slideOffset); else super.onDrawerSlide(drawerView,0); if(drawerListener != null) drawerListener.onDrawerSlide(drawerView,slideOffset); } @Override public void onDrawerStateChanged(int newState) { super.onDrawerStateChanged(newState); if(drawerListener != null) drawerListener.onDrawerStateChanged(newState); } }; layout.setDrawerListener(pulsante); } // si attacca alla usercover un listener ViewTreeObserver vto; if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) vto = usercover.getViewTreeObserver(); else vto = customDrawerHeader.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // quando l'immagine e' stata caricata // change user space to 16:9 int width = drawer.getWidth(); int heightCover; switch(drawerHeaderType) { default: case DRAWERHEADER_ACCOUNTS: case DRAWERHEADER_IMAGE: case DRAWERHEADER_CUSTOM: // si fa il rapporto in 16 : 9 heightCover = (9 * width) / 16; break; case DRAWERHEADER_NO_HEADER: // height cover viene usato per prendere l'altezza della statusbar if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !kitkatTraslucentStatusbar)) { heightCover = 0; } else { // su kitkat (con il traslucentstatusbar attivo) e su Lollipop e' 25 dp heightCover = (int) (25 * density); } break; } // set user space if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) { usercover.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, heightCover)); usercoverSwitcher.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, heightCover)); } else { customDrawerHeader.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, heightCover)); } // heightCover (DRAWER HEADER) + 8 (PADDING) + sections + 8 (PADDING) + 1 (DIVISOR) + bottomSections int heightDrawer = (int) (( ( 8 + 8 + 1) * density ) + heightCover + sections.getHeight() + ((density * 48) * bottomSectionList.size())); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !kitkatTraslucentStatusbar)) { heightDrawer += (density * 25); } // si aggiungono le bottom sections if(heightDrawer >= getHeight()) { addDivisor(); for (MaterialSection section : bottomSectionList) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (48 * density)); sections.addView(section.getView(), params); } } else for (MaterialSection section : bottomSectionList) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) (48 * density)); bottomSections.addView(section.getView(), params); } ViewTreeObserver obs; if(drawerHeaderType == DRAWERHEADER_ACCOUNTS) obs = usercover.getViewTreeObserver(); else obs = customDrawerHeader.getViewTreeObserver(); // si rimuove il listener if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { obs.removeOnGlobalLayoutListener(this); } else { obs.removeGlobalOnLayoutListener(this); } } }); MaterialSection section = null; if (savedInstanceState == null) { // init account views if(accountManager.size() > 0) { currentAccount = accountManager.get(0); notifyAccountDataChanged(); } // init section section = sectionList.get(0); } else { ArrayList<Integer> accountNumbers = savedInstanceState.getIntegerArrayList(STATE_ACCOUNT); // ripristina gli account for(int i = 0; i< accountNumbers.size(); i++) { MaterialAccount account = accountManager.get(i); account.setAccountNumber(accountNumbers.get(i)); if(account.getAccountNumber() == MaterialAccount.FIRST_ACCOUNT) currentAccount = account; } notifyAccountDataChanged(); int accountSelected = savedInstanceState.getInt(STATE_SECTION); if(accountSelected >= BOTTOM_SECTION_START) { section = bottomSectionList.get(accountSelected-BOTTOM_SECTION_START); } else section = sectionList.get(accountSelected); if(section.getTarget() != MaterialSection.TARGET_FRAGMENT) { section = sectionList.get(0); } changeToolbarColor(section); } title = section.getTitle(); currentSection = section; section.select(); setFragment((Fragment) section.getTargetFragment(), section.getTitle(), null); // learning pattern if(learningPattern) { layout.openDrawer(drawer); disableLearningPattern(); } } @Override protected void onResume() { super.onResume(); if(!deviceSupportMultiPane()) layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, drawer); else layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, drawer); } // Gestione dei Menu ----------------------------------------------------------------------------------------------------------------------------- @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. return super.onCreateOptionsMenu(menu); } /* Chiamata dopo l'invalidateOptionsMenu() */ @Override public boolean onPrepareOptionsMenu(Menu menu) { return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Se dal drawer si seleziona un oggetto if(pulsante != null) if (pulsante.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } //------------------------------------------------------------------------------------------------------------------------------------------------ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. if(pulsante != null ) pulsante.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) {// al cambio di orientamento dello schermo super.onConfigurationChanged(newConfig); // Passa tutte le configurazioni al drawer if(pulsante != null ) { pulsante.onConfigurationChanged(newConfig); } } @Override public void setTitle(CharSequence title) { this.title = title; this.getSupportActionBar().setTitle(title); } @Override public void onBackPressed() { switch(backPattern) { default: case BACKPATTERN_BACK_ANYWHERE: super.onBackPressed(); break; case BACKPATTERN_BACK_TO_FIRST: MaterialSection section = sectionList.get(0); if(currentSection == section) super.onBackPressed(); else { onClick(section); } break; case BACKPATTERN_CUSTOM: MaterialSection backedSection = backToSection(getCurrentSection()); if(currentSection == backedSection) super.onBackPressed(); else { if(backedSection.getTarget() != MaterialSection.TARGET_FRAGMENT) { throw new RuntimeException("The restored section must have a fragment as target"); } onClick(backedSection); } break; } } @Override protected void onSaveInstanceState(Bundle outState) { int position = this.getCurrentSection().getPosition(); outState.putInt(STATE_SECTION,position); ArrayList<Integer> list = new ArrayList<>(); for(MaterialAccount account : accountManager) list.add(account.getAccountNumber()); outState.putIntegerArrayList(STATE_ACCOUNT,list); super.onSaveInstanceState(outState); } @Override protected void onDestroy() { super.onDestroy(); // recycle bitmaps recycleAccounts(); } /** * Method used with BACKPATTERN_CUSTOM to retrieve the section which is restored * @param currentSection * @return the Section to restore that has Fragment as target (or currentSection for exit from activity) */ protected MaterialSection backToSection(MaterialSection currentSection) { return currentSection; } /** * TODO * @param fragment * @param title * @param oldFragment */ public void setFragment(Fragment fragment,String title,Fragment oldFragment) { // si setta il titolo setTitle(title); if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // before honeycomb there is not android.app.Fragment android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); if(oldFragment != null && oldFragment != fragment) ft.remove((android.support.v4.app.Fragment) oldFragment); ft.replace(R.id.frame_container, (android.support.v4.app.Fragment) fragment).commit(); } else if (fragment instanceof android.app.Fragment) { if (oldFragment instanceof android.support.v4.app.Fragment) throw new RuntimeException("You should use only one type of Fragment"); FragmentTransaction ft = getFragmentManager().beginTransaction(); if (oldFragment != null && fragment != oldFragment) ft.remove((android.app.Fragment) oldFragment); ft.replace(R.id.frame_container, (android.app.Fragment) fragment).commit(); } else if(fragment instanceof android.support.v4.app.Fragment) { if(oldFragment instanceof android.app.Fragment) throw new RuntimeException("You should use only one type of Fragment"); android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); if(oldFragment != null && oldFragment != fragment) ft.remove((android.support.v4.app.Fragment) oldFragment); ft.replace(R.id.frame_container, (android.support.v4.app.Fragment) fragment).commit(); } else throw new RuntimeException("Fragment must be android.app.Fragment or android.support.v4.app.Fragment"); // si chiude il drawer if(!deviceSupportMultiPane()) layout.closeDrawer(drawer); } private MaterialAccount findAccountNumber(int number) { for(MaterialAccount account : accountManager) if(account.getAccountNumber() == number) return account; return null; } private void switchAccounts(final MaterialAccount newAccount) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { final ImageView floatingImage = new ImageView(this); // si calcolano i rettangoli di inizio e fine Rect startingRect = new Rect(); Rect finalRect = new Rect(); Point offsetHover = new Point(); // 64dp primary user image / 40dp other user image = 1.6 scale float finalScale = 1.6f; final int statusBarHeight; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT && !kitkatTraslucentStatusbar)) { statusBarHeight = (int) (25 * density); } else { statusBarHeight = 0; } // si tiene traccia della foto cliccata ImageView photoClicked; if (newAccount.getAccountNumber() == MaterialAccount.SECOND_ACCOUNT) { photoClicked = userSecondPhoto; } else { photoClicked = userThirdPhoto; } photoClicked.getGlobalVisibleRect(startingRect, offsetHover); floatingImage.setImageDrawable(photoClicked.getDrawable()); // si aggiunge una view nell'esatta posizione dell'altra RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(photoClicked.getWidth(), photoClicked.getHeight()); params.setMargins(offsetHover.x, offsetHover.y - statusBarHeight, 0, 0); drawer.addView(floatingImage, params); // si setta la nuova foto di profilo sopra alla vecchia photoClicked.setImageDrawable(currentAccount.getCircularPhoto()); // si setta la nuova immagine di background da visualizzare sotto la vecchia usercoverSwitcher.setImageDrawable(newAccount.getBackground()); userphoto.getGlobalVisibleRect(finalRect); // Si calcola l'offset finale (LARGHEZZA DEL CONTAINER GRANDE - LARGHEZZA DEL CONTAINER PICCOLO / 2) e lo si applica int offset = (((finalRect.bottom - finalRect.top) - (startingRect.bottom - finalRect.top)) / 2); finalRect.offset(offset, offset - statusBarHeight); startingRect.offset(0, -statusBarHeight); // si animano le viste AnimatorSet set = new AnimatorSet(); set // si ingrandisce l'immagine e la si sposta a sinistra. .play(ObjectAnimator.ofFloat(floatingImage, View.X, startingRect.left, finalRect.left)) .with(ObjectAnimator.ofFloat(floatingImage, View.Y, startingRect.top, finalRect.top)) .with(ObjectAnimator.ofFloat(floatingImage, View.SCALE_X, 1f, finalScale)) .with(ObjectAnimator.ofFloat(floatingImage, View.SCALE_Y, 1f, finalScale)) .with(ObjectAnimator.ofFloat(userphoto, View.ALPHA, 1f, 0f)) .with(ObjectAnimator.ofFloat(usercover, View.ALPHA, 1f, 0f)) .with(ObjectAnimator.ofFloat(photoClicked, View.SCALE_X, 0f, 1f)) .with(ObjectAnimator.ofFloat(photoClicked, View.SCALE_Y, 0f, 1f)); set.setDuration(USER_CHANGE_TRANSITION); set.setInterpolator(new DecelerateInterpolator()); set.addListener(new AnimatorListenerAdapter() { @SuppressLint("NewApi") @Override public void onAnimationEnd(Animator animation) { // si carica la nuova immagine ((View) userphoto).setAlpha(1); setFirstAccountPhoto(newAccount.getCircularPhoto()); // si cancella l'imageview per l'effetto drawer.removeView(floatingImage); // si cambiano i dati utente setUserEmail(newAccount.getSubTitle()); setUsername(newAccount.getTitle()); // si cambia l'immagine soprastante setDrawerBackground(newAccount.getBackground()); // si fa tornare il contenuto della cover visibile (ma l'utente non nota nulla) ((View) usercover).setAlpha(1); // switch numbers currentAccount.setAccountNumber(newAccount.getAccountNumber()); newAccount.setAccountNumber(MaterialAccount.FIRST_ACCOUNT); // change pointer to newAccount currentAccount = newAccount; // si chiude il drawer if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); } @Override public void onAnimationCancel(Animator animation) { // se si annulla l'animazione si conclude e basta. onAnimationEnd(animation); } }); set.start(); } else { // for minor version no animation is used. // switch numbers currentAccount.setAccountNumber(newAccount.getAccountNumber()); newAccount.setAccountNumber(MaterialAccount.FIRST_ACCOUNT); // change pointer to newAccount currentAccount = newAccount; // refresh views notifyAccountDataChanged(); if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); } } private int getHeight() { int height = 0; Display display = getWindowManager().getDefaultDisplay(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { Point size = new Point(); display.getSize(size); height = size.y; } else { height = display.getHeight(); // deprecated } return height; } private boolean deviceSupportMultiPane() { if(multiPaneSupport && resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE && resources.getConfiguration().smallestScreenWidthDp >= 600) return true; else return false; } private void setSectionsTouch(boolean isTouchable) { for(MaterialSection section : sectionList) { section.setTouchable(isTouchable); } for(MaterialSection section : bottomSectionList) { section.setTouchable(isTouchable); } } private void recycleAccounts() { for(MaterialAccount account : accountManager) { account.recycle(); } } protected int darkenColor(int color) { if(color == primaryColor) return primaryDarkColor; float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= 0.8f; // value component return Color.HSVToColor(hsv); } @Override public void onClick(MaterialSection section) { switch (section.getTarget()) { case MaterialSection.TARGET_FRAGMENT: setFragment((Fragment) section.getTargetFragment(), section.getTitle(), (Fragment) currentSection.getTargetFragment()); changeToolbarColor(section); break; case MaterialSection.TARGET_ACTIVITY: this.startActivity(section.getTargetIntent()); if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); break; // TARGET_LISTENER viene gestito internamente case MaterialSection.TARGET_LISTENER: if (!deviceSupportMultiPane()) layout.closeDrawer(drawer); default: break; } currentSection = section; int position = section.getPosition(); for (MaterialSection mySection : sectionList) { if (position != mySection.getPosition()) mySection.unSelect(); } for (MaterialSection mySection : bottomSectionList) { if (position != mySection.getPosition()) mySection.unSelect(); } if(!deviceSupportMultiPane()) { drawerTouchLocked = true; setSectionsTouch(!drawerTouchLocked); } } @Override public void onUserPhotoLoaded(MaterialAccount account) { if(account.getAccountNumber() <= MaterialAccount.THIRD_ACCOUNT) notifyAccountDataChanged(); } @Override public void onBackgroundLoaded(MaterialAccount account) { if(account.getAccountNumber() <= MaterialAccount.THIRD_ACCOUNT) notifyAccountDataChanged(); } // method used for change supports public void setAccountListener(MaterialAccountListener listener) { this.accountListener = listener; } public void setDrawerListener(DrawerLayout.DrawerListener listener) { this.drawerListener = listener; } public void addMultiPaneSupport() { this.multiPaneSupport = true; } public void allowArrowAnimation() { slidingDrawerEffect = true; } public void disableLearningPattern() { learningPattern = false; } public void changeToolbarColor(MaterialSection section) { if (section.hasSectionColor()) { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) { if (!section.hasSectionColorDark()) this.statusBar.setImageDrawable(new ColorDrawable(darkenColor(section.getSectionColor()))); else this.statusBar.setImageDrawable(new ColorDrawable(section.getSectionColorDark())); } else this.statusBar.setImageDrawable(new ColorDrawable(section.getSectionColor())); this.getToolbar().setBackgroundColor(section.getSectionColor()); } else { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) this.statusBar.setImageDrawable(new ColorDrawable(darkenColor(primaryColor))); else this.statusBar.setImageDrawable(new ColorDrawable(primaryColor)); this.getToolbar().setBackgroundColor(primaryColor); } } public void changeToolbarColor(int primaryColor, int primaryDarkColor) { if(statusBar != null) this.statusBar.setImageDrawable(new ColorDrawable(primaryDarkColor)); if(getToolbar() != null) this.getToolbar().setBackgroundColor(primaryColor); } public void setBackPattern(int backPattern) { this.backPattern = backPattern; } public void setDrawerHeaderCustom(View view) { if(drawerHeaderType != DRAWERHEADER_CUSTOM) throw new RuntimeException("Your header is not setted to Custom, check in your styles.xml"); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); customDrawerHeader.addView(view,params); } public void setDrawerHeaderImage(Bitmap background) { if(drawerHeaderType != DRAWERHEADER_IMAGE) throw new RuntimeException("Your header is not setted to Image, check in your styles.xml"); ImageView image = new ImageView(this); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); image.setScaleType(ImageView.ScaleType.FIT_XY); image.setImageBitmap(background); customDrawerHeader.addView(image,params); } public void setDrawerHeaderImage(Drawable background) { if(drawerHeaderType != DRAWERHEADER_IMAGE) throw new RuntimeException("Your header is not setted to Image, check in your styles.xml"); ImageView image = new ImageView(this); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); image.setScaleType(ImageView.ScaleType.FIT_XY); image.setImageDrawable(background); customDrawerHeader.addView(image, params); } // Method used for customize layout public void setUserEmail(String email) { usermail.setText(email); } public void setUsername(String username) { this.username.setText(username); } public void setFirstAccountPhoto(Drawable photo) { userphoto.setImageDrawable(photo); } public void setSecondAccountPhoto(Drawable photo) { userSecondPhoto.setImageDrawable(photo); } public void setThirdAccountPhoto(Drawable photo) { userThirdPhoto.setImageDrawable(photo); } public void setDrawerBackground(Drawable background) { usercover.setImageDrawable(background); } public void addSection(MaterialSection section) { section.setPosition(sectionList.size()); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(48 * density)); sectionList.add(section); sections.addView(section.getView(),params); } public void addBottomSection(MaterialSection section) { section.setPosition(BOTTOM_SECTION_START + bottomSectionList.size()); //LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(48 * density)); bottomSectionList.add(section); //bottomSections.addView(section.getView(),params); } public void addDivisor() { View view = new View(this); view.setBackgroundColor(Color.parseColor("#e0e0e0")); // height 1 px LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,1); params.setMargins(0,(int) (8 * density), 0 , (int) (8 * density)); sections.addView(view, params); } public void addSubheader(CharSequence title) { View subheader = LayoutInflater.from(this).inflate(R.layout.layout_material_subheader,sections,false); TextView subheaderTitle = (TextView) subheader.findViewById(R.id.subheader_text); subheaderTitle.setText(title); // add custom separator on top of subheader View view = new View(this); view.setBackgroundColor(Color.parseColor("#e0e0e0")); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,1); params.setMargins(0,(int) (8 * density), 0 , 0); sections.addView(view,params); sections.addView(subheader); } public void addAccount(MaterialAccount account) { if(DRAWERHEADER_ACCOUNTS != drawerHeaderType) { throw new RuntimeException("Your header is not setted to Accounts, check in your styles.xml"); } if (accountManager.size() == 3) throw new RuntimeException("Currently are supported max 3 accounts"); account.setAccountListener(this); account.setAccountNumber(accountManager.size()); accountManager.add(account); } /** * Reload Application data from Account Information */ public void notifyAccountDataChanged() { switch(accountManager.size()) { case 3: this.setThirdAccountPhoto(findAccountNumber(MaterialAccount.THIRD_ACCOUNT).getCircularPhoto()); case 2: this.setSecondAccountPhoto(findAccountNumber(MaterialAccount.SECOND_ACCOUNT).getCircularPhoto()); case 1: this.setFirstAccountPhoto(currentAccount.getCircularPhoto()); this.setDrawerBackground(currentAccount.getBackground()); this.setUsername(currentAccount.getTitle()); this.setUserEmail(currentAccount.getSubTitle()); default: } } // create sections public MaterialSection newSection(String title, Drawable icon, Fragment target) { MaterialSection section = new MaterialSection<Fragment>(this,true,rippleSupport,MaterialSection.TARGET_FRAGMENT); section.setOnClickListener(this); section.setIcon(icon); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title, Drawable icon, Intent target) { MaterialSection section = new MaterialSection<Fragment>(this,true,rippleSupport,MaterialSection.TARGET_ACTIVITY); section.setOnClickListener(this); section.setIcon(icon); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title, Drawable icon, MaterialSectionListener target) { MaterialSection section = new MaterialSection<Fragment>(this,true,rippleSupport,MaterialSection.TARGET_LISTENER); section.setOnClickListener(this); section.setIcon(icon); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title, Bitmap icon,Fragment target) { MaterialSection section = new MaterialSection<Fragment>(this,true,rippleSupport,MaterialSection.TARGET_FRAGMENT); section.setOnClickListener(this); section.setIcon(icon); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title, Bitmap icon,Intent target) { MaterialSection section = new MaterialSection<Fragment>(this,true,rippleSupport,MaterialSection.TARGET_ACTIVITY); section.setOnClickListener(this); section.setIcon(icon); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title, Bitmap icon,MaterialSectionListener target) { MaterialSection section = new MaterialSection<Fragment>(this,true,rippleSupport,MaterialSection.TARGET_LISTENER); section.setOnClickListener(this); section.setIcon(icon); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title, int icon,Fragment target) { return newSection(title,resources.getDrawable(icon),target); } public MaterialSection newSection(String title, int icon,Intent target) { return newSection(title,resources.getDrawable(icon),target); } public MaterialSection newSection(String title, int icon,MaterialSectionListener target) { return newSection(title,resources.getDrawable(icon),target); } public MaterialSection newSection(String title,Fragment target) { MaterialSection section = new MaterialSection<Fragment>(this,false,rippleSupport,MaterialSection.TARGET_FRAGMENT); section.setOnClickListener(this); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title,Intent target) { MaterialSection section = new MaterialSection<Fragment>(this,false,rippleSupport,MaterialSection.TARGET_ACTIVITY); section.setOnClickListener(this); section.setTitle(title); section.setTarget(target); return section; } public MaterialSection newSection(String title,MaterialSectionListener target) { MaterialSection section = new MaterialSection<Fragment>(this,false,rippleSupport,MaterialSection.TARGET_LISTENER); section.setOnClickListener(this); section.setTitle(title); section.setTarget(target); return section; } // abstract methods public abstract void init(Bundle savedInstanceState); // get methods public Toolbar getToolbar() { return toolbar; } public MaterialSection getCurrentSection() { return currentSection; } public MaterialAccount getCurrentAccount() { return currentAccount; } public MaterialAccount getAccountAtCurrentPosition(int position) { if (position < 0 || position >= accountManager.size()) throw new RuntimeException("Account Index Overflow"); return findAccountNumber(position); } }