2015-04-23 7 views
11

ho la seguente classe:5.1 come elevazione ombra sotto una vista utilizzando OnDraw metodo

class SlidingTabStrip extends LinearLayout { 

    private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 1; 
    private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; 
    private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3; 
    private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; 

    private final int mBottomBorderThickness; 
    private final Paint mBottomBorderPaint; 

    private final int mSelectedIndicatorThickness; 
    private final Paint mSelectedIndicatorPaint; 

    private final int mDefaultBottomBorderColor; 

    private int mSelectedPosition; 
    private float mSelectionOffset; 

    private SlidingTabLayout.TabColorizer mCustomTabColorizer; 
    private final SimpleTabColorizer mDefaultTabColorizer; 

    SlidingTabStrip(Context context) { 
     this(context, null); 
    } 

    SlidingTabStrip(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setWillNotDraw(false); 

     final float density = getResources().getDisplayMetrics().density; 

     TypedValue outValue = new TypedValue(); 
     context.getTheme().resolveAttribute(Color.parseColor("#000000"), outValue, true); 
     final int themeForegroundColor = outValue.data; 

     mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor, 
       DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); 

     mDefaultTabColorizer = new SimpleTabColorizer(); 
     mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR); 

     mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); 
     mBottomBorderPaint = new Paint(); 
     mBottomBorderPaint.setColor(mDefaultBottomBorderColor); 

     mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); 
     mSelectedIndicatorPaint = new Paint(); 







    } 

    void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) { 
     mCustomTabColorizer = customTabColorizer; 
     invalidate(); 
    } 

    void setSelectedIndicatorColors(int... colors) { 
     // Make sure that the custom colorizer is removed 
     mCustomTabColorizer = null; 
     mDefaultTabColorizer.setIndicatorColors(colors); 
     invalidate(); 
    } 

    void onViewPagerPageChanged(int position, float positionOffset) { 
     mSelectedPosition = position; 
     mSelectionOffset = positionOffset; 
     invalidate(); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     final int height = getHeight(); 
     final int childCount = getChildCount(); 
     final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null ? mCustomTabColorizer : mDefaultTabColorizer; 

     // Thick colored underline below the current selection 
     if (childCount > 0) { 
      View selectedTitle = getChildAt(mSelectedPosition); 
      int left = selectedTitle.getLeft(); 
      int right = selectedTitle.getRight(); 
      int color = tabColorizer.getIndicatorColor(mSelectedPosition); 

      if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) { 
       int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1); 
       if (color != nextColor) { 
        color = blendColors(nextColor, color, mSelectionOffset); 
       } 

       // Draw the selection partway between the tabs 
       View nextTitle = getChildAt(mSelectedPosition + 1); 
       left = (int) (mSelectionOffset * nextTitle.getLeft() + 
         (1.0f - mSelectionOffset) * left); 
       right = (int) (mSelectionOffset * nextTitle.getRight() + 
         (1.0f - mSelectionOffset) * right); 
      } 

      mSelectedIndicatorPaint.setColor(color); 

      canvas.drawRect(left, height - mSelectedIndicatorThickness, right,height, mSelectedIndicatorPaint); 
     } 

     // Thin underline along the entire bottom edge 
     canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); 

    } 

    /** 
    * Set the alpha value of the {@code color} to be the given {@code alpha} value. 
    */ 
    private static int setColorAlpha(int color, byte alpha) { 
     return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 
    } 

    /** 
    * Blend {@code color1} and {@code color2} using the given ratio. 
    * 
    * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 
    *    0.0 will return {@code color2}. 
    */ 
    private static int blendColors(int color1, int color2, float ratio) { 
     final float inverseRation = 1f - ratio; 
     float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); 
     float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); 
     float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); 
     return Color.rgb((int) r, (int) g, (int) b); 
    } 

    private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer { 
     private int[] mIndicatorColors; 

     @Override 
     public final int getIndicatorColor(int position) { 
      return mIndicatorColors[position % mIndicatorColors.length]; 
     } 

     void setIndicatorColors(int... colors) { 
      mIndicatorColors = colors; 
     } 
    } 
} 

La riga seguente viene utilizzato per tracciare una linea sotto il TabStrip:

canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint); 

Se ho impostato il seguente:

private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 10; 

ottengo una linea che assomiglia a: enter image description here

Tuttavia voglio disegnare al di fuori del TabStrip, come:

enter image description here

Eventuali suggerimenti, linee guida come posso raggiungere questo obiettivo?

Va bene, come suggerito da Rod, ho cercato di usare un FrameLayout:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <!-- android:paddingTop="?android:attr/actionBarSize" --> 

    <FrameLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:foreground="@drawable/bottom_shadow" > 

     <com.example.SlidingTabLayout 
      android:id="@+id/sliding_tabs" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="@color/actionbar_bg" /> 
    </FrameLayout> 
    <!-- 
     <FrameLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:foreground="?android:windowContentOverlay" /> 
    --> 

    <android.support.v4.view.ViewPager 
     android:id="@+id/pager" 
     android:layout_width="match_parent" 
     android:layout_height="0px" 
     android:layout_weight="1" 
     android:background="@android:color/white" /> 

</LinearLayout> 

Con questa tecnica il risultato che ottiene è:

enter image description here

risposta

5

non puoi davvero aggiungere un'ombra discesa all'interno della scheda utilizzando il suo OnDraw.

quello che devi fare è avvolgere i tuoi contenuti in FrameLayout e usare il suo android:foreground e impostare un'immagine ombra che può essere trovata nelle icone di design del materiale per emulare un'ombra sopra di esso.

enter image description here questa è una immagine di nove patch. assicurarsi che se si utilizza questo dovrebbe essere percorso nella cartella drawable xhdpi con estensione come name.9.png

XML di esempio per aggiungere l'immagine qui sopra per emulare un ombra sulla parte superiore della vista:

<FrameLayout 
    android:id="@+id/fl_fragment_container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_below="@id/tool_bar" 
    android:foreground="@drawable/bottom_shadow"> 

     // your view here 

</FrameLayout> 

Edit:

<FrameLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:foreground="@drawable/bottom_shadow" > 

     <android.support.v4.view.ViewPager 
     android:id="@+id/pager" 
     android:layout_width="match_parent" 
     android:layout_height="0px" 
     android:layout_weight="1" 
     android:background="@android:color/white" /> 
    </FrameLayout> 
+0

Grazie amico, l'ho provato prima ma non mi dà proprio l'effetto di elevazione, voglio che l'elenco scorra sotto l'ombra. – User3

+0

Oh, ho dimenticato il costrittore xhdpi che hai citato, darò un altro tentativo! – User3

+0

@ User3 Dovrebbe funzionare perché l'ho appena usato ieri e la vista è al di sotto esattamente come volevi. –

2

si sarebbe probabilmente trovare this question quite useful.

Il codice pertinente:

Rect newRect = canvas.getClipBounds(); 
newRect.inset(-5, -5) // Make the Rect larger 

canvas.clipRect (myNewRect, Region.Op.REPLACE); 
// Draw shadow here 

Il Canvas è possibile aspirare fuori di sé aumentando proprio contorno di ritaglio (negativamente insetting). È quindi possibile disegnare un'ombra sul bordo inferiore.

+0

Grazie amico, lo verificherò! – User3

Problemi correlati