diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/ShadowView.java b/app/src/main/java/de/kuschku/quasseldroid/util/ui/ShadowView.java
deleted file mode 100644
index 2e30afb8ee978526854449b6ae427ce606f80beb..0000000000000000000000000000000000000000
--- a/app/src/main/java/de/kuschku/quasseldroid/util/ui/ShadowView.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.kuschku.quasseldroid.util.ui;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.PaintDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.RectShape;
-import android.os.Build;
-import android.support.annotation.Nullable;
-import android.support.annotation.RequiresApi;
-import android.util.AttributeSet;
-import android.util.LruCache;
-import android.view.Gravity;
-import android.view.View;
-
-import de.kuschku.quasseldroid.R;
-
-/**
- * Shadow view based on the {@code ScrimUtil.java} class from the Muzei App. Take a look at
- * <a href="https://plus.google.com/+RomanNurik/posts/2QvHVFWrHZf">this post</a> from Roman
- * Nurik for more details. Find the source code
- * <a href="https://github.com/romannurik/muzei/blob/master/main/src/main/java/com/google/android/apps/muzei/util/ScrimUtil.java">here</a>.
- */
-public class ShadowView extends View {
-
-  private static final LruCache<Integer, Drawable> cubicGradientScrimCache = new LruCache<>(10);
-
-  public ShadowView(Context context) {
-    super(context);
-    initialize(context, null, 0, 0);
-  }
-
-  public ShadowView(Context context, @Nullable AttributeSet attrs) {
-    super(context, attrs);
-    initialize(context, attrs, 0, 0);
-  }
-
-  public ShadowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-    super(context, attrs, defStyleAttr);
-    initialize(context, attrs, defStyleAttr, 0);
-  }
-
-  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-  public ShadowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-    super(context, attrs, defStyleAttr, defStyleRes);
-    initialize(context, attrs, defStyleAttr, defStyleRes);
-  }
-
-  /**
-   * Initializes the view.
-   *
-   * @param context      The Context the view is running in, through which it can
-   *                     access the current theme, resources, etc.
-   * @param attrs        The attributes of the XML tag that is inflating the view.
-   * @param defStyleAttr An attribute in the current theme that contains a
-   *                     reference to a style resource that supplies default values for
-   *                     the view. Can be 0 to not look for defaults.
-   * @param defStyleRes  A resource identifier of a style resource that
-   *                     supplies default values for the view, used only if
-   *                     defStyleAttr is 0 or can not be found in the theme. Can be 0
-   *                     to not look for defaults.
-   * @see View(Context, AttributeSet, int)
-   */
-  private void initialize(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-    int gravity = Gravity.TOP;
-
-    // Get the attributes.
-    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShadowView, defStyleAttr, defStyleRes);
-    try {
-      if (a != null) {
-        gravity = a.getInt(R.styleable.ShadowView_android_gravity, gravity);
-      }
-
-    } finally {
-      if (a != null) a.recycle();
-    }
-
-    // Set the gradient as background.
-    setBackground(makeCubicGradientScrimDrawable(0x44000000, 8, gravity));
-  }
-
-  /**
-   * Creates an approximated cubic gradient using a multi-stop linear gradient.
-   */
-  @SuppressLint("RtlHardcoded")
-  private Drawable makeCubicGradientScrimDrawable(int baseColor, int numStops, int gravity) {
-
-    // Generate a cache key by hashing together the inputs, based on the method described in the Effective Java book
-    int cacheKeyHash = baseColor;
-    cacheKeyHash = 31 * cacheKeyHash + numStops;
-    cacheKeyHash = 31 * cacheKeyHash + gravity;
-
-    Drawable cachedGradient = cubicGradientScrimCache.get(cacheKeyHash);
-    if (cachedGradient != null) {
-      return cachedGradient;
-    }
-
-    numStops = Math.max(numStops, 2);
-
-    PaintDrawable paintDrawable = new PaintDrawable();
-    paintDrawable.setShape(new RectShape());
-
-    final int[] stopColors = new int[numStops];
-
-    int red = Color.red(baseColor);
-    int green = Color.green(baseColor);
-    int blue = Color.blue(baseColor);
-    int alpha = Color.alpha(baseColor);
-
-    for (int i = 0; i < numStops; i++) {
-      float x = i * 1f / (numStops - 1);
-      float opacity = constrain(0, 1, (float) Math.pow(x, 3));
-      stopColors[i] = Color.argb((int) (alpha * opacity), red, green, blue);
-    }
-
-    final float x0, x1, y0, y1;
-    switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-      case Gravity.LEFT:
-        x0 = 1;
-        x1 = 0;
-        break;
-      case Gravity.RIGHT:
-        x0 = 0;
-        x1 = 1;
-        break;
-      default:
-        x0 = 0;
-        x1 = 0;
-        break;
-    }
-    switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
-      case Gravity.TOP:
-        y0 = 1;
-        y1 = 0;
-        break;
-      case Gravity.BOTTOM:
-        y0 = 0;
-        y1 = 1;
-        break;
-      default:
-        y0 = 0;
-        y1 = 0;
-        break;
-    }
-
-    paintDrawable.setShaderFactory(new ShapeDrawable.ShaderFactory() {
-      @Override
-      public Shader resize(int width, int height) {
-        return new LinearGradient(
-          width * x0,
-          height * y0,
-          width * x1,
-          height * y1,
-          stopColors, null,
-          Shader.TileMode.CLAMP);
-      }
-    });
-
-    cubicGradientScrimCache.put(cacheKeyHash, paintDrawable);
-    return paintDrawable;
-  }
-
-  private float constrain(float min, float max, float v) {
-    return Math.max(min, Math.min(max, v));
-  }
-
-}
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/ui/ShadowView.kt b/app/src/main/java/de/kuschku/quasseldroid/util/ui/ShadowView.kt
new file mode 100644
index 0000000000000000000000000000000000000000..613b438c3153d41559e9c8eabac71e9618f0fd88
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/ui/ShadowView.kt
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package de.kuschku.quasseldroid.util.ui
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Color
+import android.graphics.LinearGradient
+import android.graphics.Shader
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.PaintDrawable
+import android.graphics.drawable.ShapeDrawable
+import android.graphics.drawable.shapes.RectShape
+import android.os.Build
+import android.support.annotation.RequiresApi
+import android.util.AttributeSet
+import android.util.LruCache
+import android.view.Gravity
+import android.view.View
+import de.kuschku.quasseldroid.R
+
+/**
+ * Shadow view based on the `ScrimUtil.java` class from the Muzei App. Take a look at
+ * [this post](https://plus.google.com/+RomanNurik/posts/2QvHVFWrHZf) from Roman
+ * Nurik for more details. Find the source code
+ * [here](https://github.com/romannurik/muzei/blob/master/main/src/main/java/com/google/android/apps/muzei/util/ScrimUtil.java).
+ */
+class ShadowView : View {
+  constructor(context: Context) : super(context) {
+    initialize(context, null, 0, 0)
+  }
+
+  constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
+    initialize(context, attrs, 0, 0)
+  }
+
+  constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
+    super(context, attrs, defStyleAttr) {
+    initialize(context, attrs, defStyleAttr, 0)
+  }
+
+  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+  constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) :
+    super(context, attrs, defStyleAttr, defStyleRes) {
+    initialize(context, attrs, defStyleAttr, defStyleRes)
+  }
+
+  /**
+   * Initializes the view.
+   *
+   * @param context      The Context the view is running in, through which it can
+   * access the current theme, resources, etc.
+   * @param attrs        The attributes of the XML tag that is inflating the view.
+   * @param defStyleAttr An attribute in the current theme that contains a
+   * reference to a style resource that supplies default values for
+   * the view. Can be 0 to not look for defaults.
+   * @param defStyleRes  A resource identifier of a style resource that
+   * supplies default values for the view, used only if
+   * defStyleAttr is 0 or can not be found in the theme. Can be 0
+   * to not look for defaults.
+   * @see View
+   */
+  private fun initialize(context: Context, attrs: AttributeSet?, defStyleAttr: Int,
+                         defStyleRes: Int) {
+    var gravity = Gravity.TOP
+
+    // Get the attributes.
+    val a = context.obtainStyledAttributes(attrs, R.styleable.ShadowView, defStyleAttr, defStyleRes)
+    try {
+      if (a != null) {
+        gravity = a.getInt(R.styleable.ShadowView_android_gravity, gravity)
+      }
+
+    } finally {
+      a?.recycle()
+    }
+
+    // Set the gradient as background.
+    background = makeCubicGradientScrimDrawable(0x44000000, 8, gravity)
+  }
+
+  /**
+   * Creates an approximated cubic gradient using a multi-stop linear gradient.
+   */
+  @SuppressLint("RtlHardcoded")
+  private fun makeCubicGradientScrimDrawable(baseColor: Int, numStops: Int,
+                                             gravity: Int): Drawable {
+    // Generate a cache key by hashing together the inputs, based on the method described in the Effective Java book
+    val cacheKeyHash = ((baseColor) * 31 + numStops) * 31 + gravity
+    val cachedGradient = cubicGradientScrimCache.get(cacheKeyHash)
+    if (cachedGradient != null) {
+      return cachedGradient
+    }
+
+    val paintDrawable = PaintDrawable()
+    paintDrawable.shape = RectShape()
+
+    val red = Color.red(baseColor)
+    val green = Color.green(baseColor)
+    val blue = Color.blue(baseColor)
+    val alpha = Color.alpha(baseColor)
+
+    val stopColors = IntArray(numStops) {
+      val x = it * 1f / (numStops - 1)
+      val opacity = constrain(0f, 1f, Math.pow(x.toDouble(), 3.0).toFloat())
+      Color.argb((alpha * opacity).toInt(), red, green, blue)
+    }
+
+    val x0: Float
+    val x1: Float
+    val y0: Float
+    val y1: Float
+    when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
+      Gravity.LEFT  -> {
+        x0 = 1f
+        x1 = 0f
+      }
+      Gravity.RIGHT -> {
+        x0 = 0f
+        x1 = 1f
+      }
+      else          -> {
+        x0 = 0f
+        x1 = 0f
+      }
+    }
+    when (gravity and Gravity.VERTICAL_GRAVITY_MASK) {
+      Gravity.TOP    -> {
+        y0 = 1f
+        y1 = 0f
+      }
+      Gravity.BOTTOM -> {
+        y0 = 0f
+        y1 = 1f
+      }
+      else           -> {
+        y0 = 0f
+        y1 = 0f
+      }
+    }
+
+    paintDrawable.shaderFactory = ShadowShaderFactory(x0, y0, x1, y1, stopColors)
+    cubicGradientScrimCache.put(cacheKeyHash, paintDrawable)
+    return paintDrawable
+  }
+
+  private fun constrain(min: Float, max: Float, v: Float): Float {
+    return Math.max(min, Math.min(max, v))
+  }
+
+  class ShadowShaderFactory(
+    private val x0: Float, private val y0: Float,
+    private val x1: Float, private val y1: Float,
+    private val stopColors: IntArray
+  ) : ShapeDrawable.ShaderFactory() {
+    override fun resize(width: Int, height: Int) = LinearGradient(
+      width * x0,
+      height * y0,
+      width * x1,
+      height * y1,
+      stopColors, null,
+      Shader.TileMode.CLAMP)
+  }
+
+  companion object {
+    private val cubicGradientScrimCache = LruCache<Int, Drawable>(10)
+  }
+}