【问题标题】:5.1 like elevation Shadow under a View using onDraw method5.1 使用onDraw方法在一个View下像高程Shadow
【发布时间】:2015-07-01 05:02:01
【问题描述】:

我有以下课程:

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

下面的线用于在tabstrip下画一条线:

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

如果我设置以下:

private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 10;

我得到一条如下所示的行:

但是我想在标签条之外绘制它,例如:

任何提示,指导我如何做到这一点?

好的,按照 Rod 的建议,我尝试使用 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>

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

【问题讨论】:

    标签: android ondraw


    【解决方案1】:

    您实际上无法使用其OnDraw 在标签中添加下拉阴影。

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

    这是一个九补丁图像。确保如果您使用它,它应该位于您的 xhdpi 可绘制文件夹中,扩展名为 name.9.png

    用于添加上述图像以在视图顶部模拟阴影的示例 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>
    

    编辑:

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

    【讨论】:

    • 谢谢伙计,我以前试过这个,但它并没有给我高度的效果,我希望列表在阴影下滚动。
    • 哦,我忘了你提到的xhdpi constriant,再试一次!
    • @User3 它应该可以工作,因为我昨天刚用过它,下面的视图就像你想要的一样。
    • 我已经更新了问题,请最后参考编辑。
    • @User3 Viewpager 应该在框架布局中,而不是在滑动标签布局中。请参阅上面的编辑。
    【解决方案2】:

    你可能会找到this question quite useful

    相关代码:

    Rect newRect = canvas.getClipBounds();
    newRect.inset(-5, -5)  // Make the Rect larger
    
    canvas.clipRect (myNewRect, Region.Op.REPLACE);
    // Draw shadow here
    

    Canvas 能够通过增加自己的剪切边界(负向内嵌)来绘制自身外部。然后您可以在底部边缘绘制阴影。

    【讨论】:

    • 谢谢老哥,我去看看!
    猜你喜欢
    • 1970-01-01
    • 2021-05-26
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    相关资源
    最近更新 更多