Android 5.1使用onDraw方法在视图下创建类似立面阴影

Android 5.1使用onDraw方法在视图下创建类似立面阴影,android,ondraw,Android,Ondraw,我有以下课程: 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_THICK

我有以下课程:

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;
        }
    }
}
如果我设置以下内容:

private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 10;
我得到一条线,看起来像:

但是我想在tabstrip之外绘制它,比如:

有什么提示和指导方针吗?我如何做到这一点

好的,正如Rod所建议的,我尝试使用框架布局:

<?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>

使用此技术,我得到的结果是:


您不能使用其
OnDraw
在选项卡内添加下拉阴影

您需要做的是将内容包装在
FrameLayout
中,并使用其
android:foreground
设置一个阴影图像,可以在材质设计图标中找到该阴影图像,以模拟其顶部的阴影

这是一张九块的图片。确保如果您使用此文件,它应该位于扩展名为name.9.png的xhdpi drawable文件夹中

用于添加上述图像以模拟视图顶部阴影的示例xml:

<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>

//你在这里的看法
编辑:


您可能会发现

相关代码:

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

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

Canvas
可以通过增加其自身的剪裁边界(负向插入)来在其外部绘制。然后你可以在底边画一个阴影。

谢谢,伙计,我以前试过这个,但它没有给我足够的提升效果,我想让列表在阴影下滚动。哦,我忘了你提到的xhdpi constriant,我会再试一次@User3它应该可以工作,因为我昨天刚刚使用过它,下面的视图与您想要的一样。我已经更新了问题,请最后参考编辑。@User3 Viewpager应该在framelayout中,而不是slidingtab布局中。请看上面的编辑。谢谢,伙计,我会查出来的!
<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>
Rect newRect = canvas.getClipBounds();
newRect.inset(-5, -5)  // Make the Rect larger

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