Search code examples
javaandroiduser-interfacekotlinlight

How to create a light emitting background in android?


I am working on an app that should have a background like this:

enter image description here

But I really could not find any tutorial how to implement this kind of design. Maybe I was using wrong keywords in my google search as most of them would lead me to instagram background tutorials.

Could anyone help me on this or tell me where to start from?


Solution

  • After searching a lot, I really could not find anything on the internet. So I tried to draw it from scratch. It's not perfect, so I'll try to make it better in the future. You need to do some trigonometric math to draw some sectors. Then use a gradient to create the fade-out effect. Here is my code:

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.LinearGradient;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.util.AttributeSet;
    import android.view.View;
    
    import androidx.annotation.Nullable;
    
    public class SpotLightsView extends View {
        private static final String TAG = SpotLightsView.class.getSimpleName();
        private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
        private double angleDegree = 10;
        private double angleRadian = Math.toRadians(angleDegree);
        private final double dTheta = angleRadian;
        private double WIDTH = 100;
        private double HEIGHT = 100;
        private double RADIUS = (1.4142*WIDTH/2); // r = a*sqrt(2);
        private double cx = WIDTH/2;
        private double cy = HEIGHT/2;
    
        public SpotLightsView(Context context) {
            super(context);
        }
    
        public SpotLightsView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public SpotLightsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            WIDTH = canvas.getWidth();
            HEIGHT = canvas.getHeight();
    
            cx = WIDTH/2;
            cy = HEIGHT/2;
    
            RADIUS = cy*1.4142;   // r = a*sqrt(2);
            drawSpotLights(canvas);
        }
    
        private void drawSpotLights(Canvas canvas) {
            double theta = 0;
            for(int i=0; i<360/angleDegree; i++){
                drawSpotLightOn(canvas, theta);
                theta+=dTheta;
            }
        }
    
        private void drawSpotLightOn(Canvas canvas, double theta){
            double x1, y1, x2, y2, x3, y3, sinTheta, cosTheta;
            double r = 50;
            sinTheta = Math.sin(theta);
            cosTheta = Math.cos(theta);
    
            x1 = cx + RADIUS*cosTheta;
            y1 = cy + RADIUS*sinTheta;
    
            x2 = x1 + r*sinTheta;
            y2 = y1 - r*cosTheta;
    
            x3 = x1 - r*sinTheta;
            y3 = y1 + r*cosTheta;
    
            LinearGradient linearGradient = new LinearGradient((float)cx,(float)cy,(float)x1,(float)y1, 0x88ffffff,
                    0x00000000, android.graphics.Shader.TileMode.CLAMP);
    
            mPaint.setDither(true);
            mPaint.setShader(linearGradient);
            mPaint.setStyle(Paint.Style.FILL);
    
            Path path = new Path();
            path.moveTo((float)cx, (float)cy);
            path.lineTo((float)x3, (float)y3);
            path.quadTo((float)x1, (float)y1, (float)x2, (float)y2);
            path.lineTo((float)cx, (float)cy);
    
            canvas.drawPath(path, mPaint);
        }
    }
    
    

    And then use it like this way inside your some_layout.xml file:

    <com.applications.customviews.demo.SpotLightsView
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    

    The output looks like this: enter image description here

    short explanation

    Change the private double angleDegree = 10; to specifiy how many degree later you want a spotlight. Then we increment the angles in a for loop and call private void drawSpotLightOn(Canvas canvas, double theta) method. On 2nd line, there is a value double r=50. It tells the code how wide the arc should be at the ending points. Change these 2 and see results to get your desired output. To make the fade-out effect, I used LinearGradient.

    The rest of the code is straight forward. You can find them in any android Paint, CustomView tutorials.