在运行时设置渐变半径并将其置于按钮周围

时间:2013-10-29 18:00:53

标签: android gradient radial-gradients

像这里列出的许多其他帖子一样,我在使用径向渐变。 发布123 ...

我想要两件事:

  1. 围绕按钮设置渐变,该按钮具有选择器作为背景可绘制以获得光环效果
  2. 调整此渐变半径以使其具有与屏幕分辨率/大小无关的相同感觉。
  3. 到目前为止我做了什么: 解决方案1 ​​

    我试图实现几种解决方案。我在这里展示了我最好的两次尝试。我用渐变设置了一个渐变到我的按钮周围的封闭布局的背景。这符合要点1)

    <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/custom_background"
            android:gravity="center"
            android:padding="@dimen/padding_extra_large" >
    
            <Button
                android:id="@+id/snap_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/custom_button" />
    </FrameLayout>
    

    这是我的@drawable/custom_background

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <item>
    
        <!-- Circular gradient -->
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle" >
            <gradient
                android:endColor="#ffdbdbdb"
                android:gradientRadius="180"
                android:startColor="#ff000000"
                android:type="radial" 
                android:innerRadiusRatio="2"
                />
        </shape>
    </item>
    

    到目前为止我做了什么: 解决方案2

    效果很好,但必须针对每个屏幕调整android:gradientRadius="180"。 Post 1提供了一些解决方案,我尝试自定义布局和视图,但我得到了崩溃。某些配置没有失败(背景设置为根布局,但在这种情况下,onDraw从未被调用)。

    自定义视图:

    public class GradientView extends View {
    
    Paint paint;
    RadialGradient gradient;
    int maxSize;
    
    public GradientView(Context context) {
        super(context);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.setWillNotDraw(false);
        // TODO Auto-generated constructor stub
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        Dbg.e("RelativeLayoutSnapBook", " -  onDraw !!!");
        maxSize = Math.max(getHeight(), getWidth());
        RadialGradient gradient = new RadialGradient(
                getWidth()/2,
                getHeight()/2,
                maxSize, 
                new int[] {Color.RED, Color.BLACK},
                new float[] {0, 1}, 
                android.graphics.Shader.TileMode.CLAMP);
    
        paint.setDither(true);
        paint.setShader(gradient);
    
        canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
    }
    }
    

    这个观点在这里:

            <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="@dimen/padding_extra_large" >
    
            <com.snapcar.rider.widget.GradientView
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
    
            <Button
                android:id="@+id/snap_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/snap_button" />
        </FrameLayout>
    

    这是失败:使用堆栈和内部错误堆栈扩充片段时出错:

    10-29 18:55:25.794: E/AndroidRuntime(11828): FATAL EXCEPTION: main
    10-29 18:55:25.794: E/AndroidRuntime(11828): android.view.InflateException: Binary XML file line #33: Error inflating class com.xxx.widget.GradientView
    10-29 18:55:25.794: E/AndroidRuntime(11828): Caused by: java.lang.ClassNotFoundException: com.xxx.rider.widget.GradientView in loader dalvik.system.PathClassLoader[/system/framework/com.google.android.maps.jar:/data/app/com.snapcar.rider-1.apk]
    
    你能帮帮我吗?非常感谢!

    编辑:某人?

1 个答案:

答案 0 :(得分:0)

我解决了!这么麻烦:/如果你了解Photoshop,我觉得你最好还是顺其自然!

感谢这篇帖子让我走的路:multiple-gradrient只使用了第一个代码提取,但如果你到达这篇帖子,整篇文章可能会让你感兴趣。

所以我使用全局布局上的回调完全用代码定义渐变:

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.v(TAG, "- onCreateView Fragment");
    root = inflater.inflate(R.layout.fragment_layout, null);
    root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Log.e(TAG, "- On Layout Completed ! ");
            final FrameLayout frame = (FrameLayout) root.findViewById(R.id.frame_layout_gradient);
            ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
                @Override
                public Shader resize(int width, int height) {
                    Log.e(TAG, " - onGlobalLayout : getWidth = "+ frame.getWidth() +" - getHeight = "+ frame.getHeight() );
                    RadialGradient lg = new RadialGradient(frame.getWidth()/2, frame.getHeight()/2, 
                            frame.getWidth()/2, Color.BLACK, Color.parseColor("#FFdbdbdb"),  TileMode.CLAMP);
                    return lg;
                }
            };
            PaintDrawable p = new PaintDrawable();
            p.setShape(new OvalShape());
            p.setShaderFactory(sf);
            frame.setBackgroundDrawable((Drawable)p);
        }
    }
            );

这个技巧Color.parseColor("#FFdbdbdb")是必需的,因为RadialGradient的延迟构造函数无法正确读取对R.color.the_gray_I_want的引用

OvalShape在我的情况下做了一个圆,因为我的frameLayout是方形的。

使用此解决方案,您的阴影完全独立于屏幕特征。

![结果 - 从SG3到HTC野火不变!1