From 496ecb7ca965709e2734e3a729853114f1741b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Fri, 29 Aug 2025 14:08:16 +0200 Subject: [PATCH 1/4] build: migration of ui package --- .../demo/ClusterAlgorithmsDemoActivity.kt | 34 +- .../src/main/res/layout/multi_profile_two.xml | 39 +++ gradle/libs.versions.toml | 2 + library/build.gradle.kts | 1 + .../google/maps/android/ui/AnimationUtil.java | 110 ------- .../google/maps/android/ui/AnimationUtil.kt | 101 ++++++ .../maps/android/ui/BubbleDrawable.java | 88 ----- .../google/maps/android/ui/BubbleDrawable.kt | 74 +++++ .../maps/android/ui/BubbleIconFactory.java | 24 -- .../google/maps/android/ui/IconGenerator.java | 303 ------------------ .../google/maps/android/ui/IconGenerator.kt | 260 +++++++++++++++ .../maps/android/ui/RotationLayout.java | 83 ----- .../google/maps/android/ui/RotationLayout.kt | 74 +++++ .../maps/android/ui/SquareTextView.java | 68 ---- .../google/maps/android/ui/SquareTextView.kt | 59 ++++ .../maps/android/ui/IconGeneratorTest.kt | 67 ++++ 16 files changed, 706 insertions(+), 681 deletions(-) create mode 100644 demo/src/main/res/layout/multi_profile_two.xml delete mode 100644 library/src/main/java/com/google/maps/android/ui/AnimationUtil.java create mode 100644 library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt delete mode 100644 library/src/main/java/com/google/maps/android/ui/BubbleDrawable.java create mode 100644 library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt delete mode 100644 library/src/main/java/com/google/maps/android/ui/BubbleIconFactory.java delete mode 100644 library/src/main/java/com/google/maps/android/ui/IconGenerator.java create mode 100644 library/src/main/java/com/google/maps/android/ui/IconGenerator.kt delete mode 100644 library/src/main/java/com/google/maps/android/ui/RotationLayout.java create mode 100644 library/src/main/java/com/google/maps/android/ui/RotationLayout.kt delete mode 100644 library/src/main/java/com/google/maps/android/ui/SquareTextView.java create mode 100644 library/src/main/java/com/google/maps/android/ui/SquareTextView.kt create mode 100644 library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt diff --git a/demo/src/main/java/com/google/maps/android/utils/demo/ClusterAlgorithmsDemoActivity.kt b/demo/src/main/java/com/google/maps/android/utils/demo/ClusterAlgorithmsDemoActivity.kt index 93e275907..d1f27fbe5 100644 --- a/demo/src/main/java/com/google/maps/android/utils/demo/ClusterAlgorithmsDemoActivity.kt +++ b/demo/src/main/java/com/google/maps/android/utils/demo/ClusterAlgorithmsDemoActivity.kt @@ -16,15 +16,16 @@ package com.google.maps.android.utils.demo +import android.os.Build +import android.util.DisplayMetrics import android.view.View +import android.view.WindowManager import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.Spinner import com.google.android.gms.maps.CameraUpdateFactory -import com.google.android.gms.maps.MapView import com.google.android.gms.maps.model.LatLng import com.google.maps.android.clustering.ClusterManager -import com.google.maps.android.clustering.algo.AbstractAlgorithm import com.google.maps.android.clustering.algo.CentroidNonHierarchicalDistanceBasedAlgorithm import com.google.maps.android.clustering.algo.ContinuousZoomEuclideanCentroidAlgorithm import com.google.maps.android.clustering.algo.GridBasedAlgorithm @@ -40,7 +41,6 @@ import kotlin.random.Random class ClusterAlgorithmsDemoActivity : BaseDemoActivity() { private var clusterManager: ClusterManager? = null - private lateinit var mapView: MapView override fun getLayoutId(): Int { return R.layout.activity_cluster_algorithms_demo @@ -85,6 +85,28 @@ class ClusterAlgorithmsDemoActivity : BaseDemoActivity() { * Sets up the ClusterManager with the chosen algorithm and populates it with items. */ private fun setupClusterer(algorithmPosition: Int) { + + val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager + val metrics = DisplayMetrics() + val width: Int + val height: Int + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // For devices with Android 11 (API 30) and above + val windowMetrics = windowManager.currentWindowMetrics + width = windowMetrics.bounds.width() + height = windowMetrics.bounds.height() + metrics.density = resources.displayMetrics.density + } else { + // For devices below Android 11 + windowManager.defaultDisplay.getMetrics(metrics) + width = metrics.widthPixels + height = metrics.heightPixels + } + + val widthDp = (width / metrics.density).toInt() + val heightDp = (height / metrics.density).toInt() + // 1. Clear the map and previous cluster manager map.clear() @@ -96,9 +118,11 @@ class ClusterAlgorithmsDemoActivity : BaseDemoActivity() { 1 -> GridBasedAlgorithm() 2 -> NonHierarchicalDistanceBasedAlgorithm() 3 -> CentroidNonHierarchicalDistanceBasedAlgorithm() - 4 -> NonHierarchicalViewBasedAlgorithm(mapView.width, mapView.height) + 4 -> NonHierarchicalViewBasedAlgorithm(widthDp, heightDp) 5 -> ContinuousZoomEuclideanCentroidAlgorithm() - else -> error("Unsupported algorithm position: $algorithmPosition") + else -> { + GridBasedAlgorithm() + } } // 4. Point the map's listeners to the ClusterManager diff --git a/demo/src/main/res/layout/multi_profile_two.xml b/demo/src/main/res/layout/multi_profile_two.xml new file mode 100644 index 000000000..f90804dc0 --- /dev/null +++ b/demo/src/main/res/layout/multi_profile_two.xml @@ -0,0 +1,39 @@ + + + + + + + + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 61ddd0a0c..56f3b53f8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,6 +17,7 @@ play-services-maps = "19.2.0" core-ktx = "1.16.0" robolectric = "4.15.1" kxml2 = "2.3.0" +androidx-test-core = "1.5.0" mockk = "1.14.5" lint = "31.12.0" org-jacoco-core = "0.8.13" @@ -43,6 +44,7 @@ play-services-maps = { module = "com.google.android.gms:play-services-maps", ver core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" } robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } kxml2 = { module = "net.sf.kxml:kxml2", version.ref = "kxml2" } +androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test-core" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } lint-api = { module = "com.android.tools.lint:lint-api", version.ref = "lint" } lint-checks = { module = "com.android.tools.lint:lint-checks", version.ref = "lint" } diff --git a/library/build.gradle.kts b/library/build.gradle.kts index 5b1f841a4..345702e55 100644 --- a/library/build.gradle.kts +++ b/library/build.gradle.kts @@ -70,6 +70,7 @@ dependencies { testImplementation(libs.mockk) testImplementation(libs.kotlin.test) testImplementation(libs.truth) + testImplementation(libs.androidx.test.core) implementation(libs.kotlin.stdlib.jdk8) } diff --git a/library/src/main/java/com/google/maps/android/ui/AnimationUtil.java b/library/src/main/java/com/google/maps/android/ui/AnimationUtil.java deleted file mode 100644 index 6aad46f0c..000000000 --- a/library/src/main/java/com/google/maps/android/ui/AnimationUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2023 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 com.google.maps.android.ui; - - -import android.os.Handler; -import android.os.SystemClock; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.Marker; - -/** - * Animation utilities for markers with Maps API. - *

- */ -public class AnimationUtil { - - /** - * Animates a marker from it's current position to the provided finalPosition - * - * @param marker marker to animate - * @param finalPosition the final position of the marker after the animation - */ - public static void animateMarkerTo(final Marker marker, final LatLng finalPosition) { - animateMarkerTo(marker, finalPosition, 2000); // delegate to new version - } - - - /** - * Animates a marker from its current position to the provided finalPosition. - * - * @param marker marker to animate - * @param finalPosition the final position of the marker after the animation - * @param durationInMs the duration of the animation in milliseconds - */ - public static void animateMarkerTo( - final Marker marker, - final LatLng finalPosition, - final long durationInMs - ) { - final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.Linear(); - final LatLng startPosition = marker.getPosition(); - final Handler handler = new Handler(); - final long start = SystemClock.uptimeMillis(); - final Interpolator interpolator = new AccelerateDecelerateInterpolator(); - - handler.post(new Runnable() { - long elapsed; - - float t; - - float v; - - @Override - public void run() { - // Calculate progress using interpolator - elapsed = SystemClock.uptimeMillis() - start; - t = elapsed / (float) durationInMs; - v = interpolator.getInterpolation(t); - - marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition)); - - // Repeat till progress is complete. - if (t < 1) { - // Post again 16ms later. - handler.postDelayed(this, 16); - } - } - }); - } - - /** - * For other LatLngInterpolator interpolators, see link here - */ - interface LatLngInterpolator { - - LatLng interpolate(float fraction, LatLng a, LatLng b); - - class Linear implements LatLngInterpolator { - - @Override - public LatLng interpolate(float fraction, LatLng a, LatLng b) { - double lat = (b.latitude - a.latitude) * fraction + a.latitude; - double lngDelta = b.longitude - a.longitude; - - // Take the shortest path across the 180th meridian. - if (Math.abs(lngDelta) > 180) { - lngDelta -= Math.signum(lngDelta) * 360; - } - double lng = lngDelta * fraction + a.longitude; - return new LatLng(lat, lng); - } - } - } -} \ No newline at end of file diff --git a/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt b/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt new file mode 100644 index 000000000..e6364e7c2 --- /dev/null +++ b/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt @@ -0,0 +1,101 @@ +/* + * Copyright 2023 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 com.google.maps.android.ui + +import android.os.Handler +import android.os.Looper +import android.os.SystemClock +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.Interpolator +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.Marker +import kotlin.math.abs +import kotlin.math.sign + +/** + * Animation utilities for markers with Maps API. + */ +object AnimationUtil { + /** + * Animates a marker from it's current position to the provided finalPosition + * + * @param marker marker to animate + * @param finalPosition the final position of the marker after the animation + */ + @JvmStatic + fun animateMarkerTo(marker: Marker, finalPosition: LatLng) { + animateMarkerTo(marker, finalPosition, 2000) // delegate to new version + } + + /** + * Animates a marker from its current position to the provided finalPosition. + * + * @param marker marker to animate + * @param finalPosition the final position of the marker after the animation + * @param durationInMs the duration of the animation in milliseconds + */ + @JvmStatic + fun animateMarkerTo( + marker: Marker, + finalPosition: LatLng, + durationInMs: Long + ) { + val latLngInterpolator: LatLngInterpolator = LatLngInterpolator.Linear() + val startPosition = marker.position + val handler = Handler(Looper.getMainLooper()) + val start = SystemClock.uptimeMillis() + val interpolator: Interpolator = AccelerateDecelerateInterpolator() + handler.post(object : Runnable { + var elapsed: Long = 0 + var t = 0f + var v = 0f + override fun run() { + // Calculate progress using interpolator + elapsed = SystemClock.uptimeMillis() - start + t = elapsed / durationInMs.toFloat() + v = interpolator.getInterpolation(t) + marker.position = latLngInterpolator.interpolate(v, startPosition, finalPosition) + + // Repeat till progress is complete. + if (t < 1) { + // Post again 16ms later. + handler.postDelayed(this, 16) + } + } + }) + } + + /** + * For other LatLngInterpolator interpolators, see [this link](https://gist.github.com/broady/6314689) + */ + fun interface LatLngInterpolator { + fun interpolate(fraction: Float, a: LatLng, b: LatLng): LatLng + class Linear : LatLngInterpolator { + override fun interpolate(fraction: Float, a: LatLng, b: LatLng): LatLng { + val lat = (b.latitude - a.latitude) * fraction + a.latitude + var lngDelta = b.longitude - a.longitude + + // Take the shortest path across the 180th meridian. + if (abs(lngDelta) > 180) { + lngDelta -= sign(lngDelta) * 360 + } + val lng = lngDelta * fraction + a.longitude + return LatLng(lat, lng) + } + } + } +} diff --git a/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.java b/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.java deleted file mode 100644 index fb33c9273..000000000 --- a/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2023 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 com.google.maps.android.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.PixelFormat; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; - -import com.google.maps.android.R; - -import androidx.core.content.ContextCompat; - -/** - * Draws a bubble with a shadow, filled with any color. - */ -class BubbleDrawable extends Drawable { - - private final Drawable mShadow; - private final Drawable mMask; - private int mColor = Color.WHITE; - - public BubbleDrawable(Context context) { - mMask = ContextCompat.getDrawable(context, R.drawable.amu_bubble_mask); - mShadow = ContextCompat.getDrawable(context, R.drawable.amu_bubble_shadow); - } - - public void setColor(int color) { - mColor = color; - } - - @Override - public void draw(Canvas canvas) { - mMask.draw(canvas); - canvas.drawColor(mColor, PorterDuff.Mode.SRC_IN); - mShadow.draw(canvas); - } - - @Override - public void setAlpha(int alpha) { - throw new UnsupportedOperationException(); - } - - @Override - public void setColorFilter(ColorFilter cf) { - throw new UnsupportedOperationException(); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - @Override - public void setBounds(int left, int top, int right, int bottom) { - mMask.setBounds(left, top, right, bottom); - mShadow.setBounds(left, top, right, bottom); - } - - @Override - public void setBounds(Rect bounds) { - mMask.setBounds(bounds); - mShadow.setBounds(bounds); - } - - @Override - public boolean getPadding(Rect padding) { - return mMask.getPadding(padding); - } -} diff --git a/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt b/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt new file mode 100644 index 000000000..c5686b830 --- /dev/null +++ b/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2023 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 com.google.maps.android.ui + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.ColorFilter +import android.graphics.PixelFormat +import android.graphics.PorterDuff +import android.graphics.Rect +import android.graphics.drawable.Drawable +import androidx.core.content.ContextCompat +import com.google.maps.android.R + +/** + * Draws a bubble with a shadow, filled with any color. + */ +internal class BubbleDrawable(context: Context) : Drawable() { + private val shadow: Drawable + private val mask: Drawable + var color = Color.WHITE + + init { + mask = ContextCompat.getDrawable(context, R.drawable.amu_bubble_mask)!! + shadow = ContextCompat.getDrawable(context, R.drawable.amu_bubble_shadow)!! + } + + override fun draw(canvas: Canvas) { + mask.draw(canvas) + canvas.drawColor(color, PorterDuff.Mode.SRC_IN) + shadow.draw(canvas) + } + + override fun setAlpha(alpha: Int) { + throw UnsupportedOperationException() + } + + override fun setColorFilter(cf: ColorFilter?) { + throw UnsupportedOperationException() + } + + override fun getOpacity(): Int { + return PixelFormat.TRANSLUCENT + } + + override fun setBounds(left: Int, top: Int, right: Int, bottom: Int) { + mask.setBounds(left, top, right, bottom) + shadow.setBounds(left, top, right, bottom) + } + + override fun setBounds(bounds: Rect) { + mask.setBounds(bounds) + shadow.setBounds(bounds) + } + + override fun getPadding(padding: Rect): Boolean { + return mask.getPadding(padding) + } +} \ No newline at end of file diff --git a/library/src/main/java/com/google/maps/android/ui/BubbleIconFactory.java b/library/src/main/java/com/google/maps/android/ui/BubbleIconFactory.java deleted file mode 100644 index 9c2c5ce79..000000000 --- a/library/src/main/java/com/google/maps/android/ui/BubbleIconFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2013 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 com.google.maps.android.ui; - -/** - * Use {@link IconGenerator} instead. - */ -@Deprecated -public class BubbleIconFactory { -} diff --git a/library/src/main/java/com/google/maps/android/ui/IconGenerator.java b/library/src/main/java/com/google/maps/android/ui/IconGenerator.java deleted file mode 100644 index 37eb3e5e5..000000000 --- a/library/src/main/java/com/google/maps/android/ui/IconGenerator.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2013 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 com.google.maps.android.ui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.maps.android.R; - -/** - * IconGenerator generates icons that contain text (or custom content) within an info - * window-like shape. - *

- * The icon {@link Bitmap}s generated by the factory should be used in conjunction with a {@link - * com.google.android.gms.maps.model.BitmapDescriptorFactory}. - *

- * This class is not thread safe. - */ -public class IconGenerator { - private final Context mContext; - - private ViewGroup mContainer; - private RotationLayout mRotationLayout; - private TextView mTextView; - private View mContentView; - - private int mRotation; - - private float mAnchorU = 0.5f; - private float mAnchorV = 1f; - private BubbleDrawable mBackground; - - /** - * Creates a new IconGenerator with the default style. - */ - public IconGenerator(Context context) { - mContext = context; - mBackground = new BubbleDrawable(mContext); - mContainer = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.amu_text_bubble, null); - mRotationLayout = (RotationLayout) mContainer.getChildAt(0); - mContentView = mTextView = (TextView) mRotationLayout.findViewById(R.id.amu_text); - setStyle(STYLE_DEFAULT); - } - - /** - * Sets the text content, then creates an icon with the current style. - * - * @param text the text content to display inside the icon. - */ - public Bitmap makeIcon(CharSequence text) { - if (mTextView != null) { - mTextView.setText(text); - } - - return makeIcon(); - } - - /** - * Creates an icon with the current content and style. - *

- * This method is useful if a custom view has previously been set, or if text content is not - * applicable. - */ - public Bitmap makeIcon() { - int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); - mContainer.measure(measureSpec, measureSpec); - - int measuredWidth = mContainer.getMeasuredWidth(); - int measuredHeight = mContainer.getMeasuredHeight(); - - mContainer.layout(0, 0, measuredWidth, measuredHeight); - - if (mRotation == 1 || mRotation == 3) { - measuredHeight = mContainer.getMeasuredWidth(); - measuredWidth = mContainer.getMeasuredHeight(); - } - - Bitmap r = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888); - r.eraseColor(Color.TRANSPARENT); - - Canvas canvas = new Canvas(r); - switch (mRotation) { - case 0: - // do nothing - break; - case 1: - canvas.translate(measuredWidth, 0); - canvas.rotate(90); - break; - case 2: - canvas.rotate(180, measuredWidth / 2, measuredHeight / 2); - break; - case 3: - canvas.translate(0, measuredHeight); - canvas.rotate(270); - break; - } - mContainer.draw(canvas); - return r; - } - - /** - * Sets the child view for the icon. - *

- * If the view contains a {@link TextView} with the id "text", operations such as {@link - * #setTextAppearance} and {@link #makeIcon(CharSequence)} will operate upon that {@link TextView}. - */ - public void setContentView(View contentView) { - mRotationLayout.removeAllViews(); - mRotationLayout.addView(contentView); - mContentView = contentView; - final View view = mRotationLayout.findViewById(R.id.amu_text); - mTextView = view instanceof TextView ? (TextView) view : null; - } - - /** - * Rotates the contents of the icon. - * - * @param degrees the amount the contents should be rotated, as a multiple of 90 degrees. - */ - public void setContentRotation(int degrees) { - mRotationLayout.setViewRotation(degrees); - } - - /** - * Rotates the icon. - * - * @param degrees the amount the icon should be rotated, as a multiple of 90 degrees. - */ - public void setRotation(int degrees) { - mRotation = ((degrees + 360) % 360) / 90; - } - - - /** - * @return u coordinate of the anchor, with rotation applied. - */ - public float getAnchorU() { - return rotateAnchor(mAnchorU, mAnchorV); - } - - /** - * @return v coordinate of the anchor, with rotation applied. - */ - public float getAnchorV() { - return rotateAnchor(mAnchorV, mAnchorU); - } - - /** - * Rotates the anchor around (u, v) = (0, 0). - */ - private float rotateAnchor(float u, float v) { - switch (mRotation) { - case 0: - return u; - case 1: - return 1 - v; - case 2: - return 1 - u; - case 3: - return v; - } - throw new IllegalStateException(); - } - - /** - * Sets the text color, size, style, hint color, and highlight color from the specified - * TextAppearance resource. - * - * @param resid the identifier of the resource. - */ - public void setTextAppearance(Context context, int resid) { - if (mTextView != null) { - mTextView.setTextAppearance(context, resid); - } - } - - /** - * Sets the text color, size, style, hint color, and highlight color from the specified - * TextAppearance resource. - * - * @param resid the identifier of the resource. - */ - public void setTextAppearance(int resid) { - setTextAppearance(mContext, resid); - } - - /** - * Sets the style of the icon. The style consists of a background and text appearance. - */ - public void setStyle(int style) { - setColor(getStyleColor(style)); - setTextAppearance(mContext, getTextStyle(style)); - } - - /** - * Sets the background to the default, with a given color tint. - * - * @param color the color for the background tint. - */ - public void setColor(int color) { - mBackground.setColor(color); - setBackground(mBackground); - } - - /** - * Set the background to a given Drawable, or remove the background. - * - * @param background the Drawable to use as the background, or null to remove the background. - */ - @SuppressWarnings("deprecation") - // View#setBackgroundDrawable is compatible with pre-API level 16 (Jelly Bean). - public void setBackground(Drawable background) { - mContainer.setBackgroundDrawable(background); - - // Force setting of padding. - // setBackgroundDrawable does not call setPadding if the background has 0 padding. - if (background != null) { - Rect rect = new Rect(); - background.getPadding(rect); - mContainer.setPadding(rect.left, rect.top, rect.right, rect.bottom); - } else { - mContainer.setPadding(0, 0, 0, 0); - } - } - - /** - * Sets the padding of the content view. The default padding of the content view (i.e. text - * view) is 5dp top/bottom and 10dp left/right. - * - * @param left the left padding in pixels. - * @param top the top padding in pixels. - * @param right the right padding in pixels. - * @param bottom the bottom padding in pixels. - */ - public void setContentPadding(int left, int top, int right, int bottom) { - mContentView.setPadding(left, top, right, bottom); - } - - public static final int STYLE_DEFAULT = 1; - public static final int STYLE_WHITE = 2; - public static final int STYLE_RED = 3; - public static final int STYLE_BLUE = 4; - public static final int STYLE_GREEN = 5; - public static final int STYLE_PURPLE = 6; - public static final int STYLE_ORANGE = 7; - - private static int getStyleColor(int style) { - switch (style) { - default: - case STYLE_DEFAULT: - case STYLE_WHITE: - return 0xffffffff; - case STYLE_RED: - return 0xffcc0000; - case STYLE_BLUE: - return 0xff0099cc; - case STYLE_GREEN: - return 0xff669900; - case STYLE_PURPLE: - return 0xff9933cc; - case STYLE_ORANGE: - return 0xffff8800; - } - } - - private static int getTextStyle(int style) { - switch (style) { - default: - case STYLE_DEFAULT: - case STYLE_WHITE: - return R.style.amu_Bubble_TextAppearance_Dark; - case STYLE_RED: - case STYLE_BLUE: - case STYLE_GREEN: - case STYLE_PURPLE: - case STYLE_ORANGE: - return R.style.amu_Bubble_TextAppearance_Light; - } - } -} diff --git a/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt b/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt new file mode 100644 index 000000000..9dbf38615 --- /dev/null +++ b/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt @@ -0,0 +1,260 @@ +/* + * Copyright 2013 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 com.google.maps.android.ui + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import com.google.maps.android.R +import androidx.core.graphics.createBitmap + +/** + * IconGenerator generates icons that contain text (or custom content) within an info + * window-like shape. + * + * + * The icon [Bitmap]s generated by the factory should be used in conjunction with a [com.google.android.gms.maps.model.BitmapDescriptorFactory]. + * + * + * This class is not thread safe. + */ +class IconGenerator(private val context: Context) { + private var container: ViewGroup = + LayoutInflater.from(context).inflate(R.layout.amu_text_bubble, null) as ViewGroup + private var rotationLayout: RotationLayout = container.getChildAt(0) as RotationLayout + private var textView: TextView? = null + private var contentView: View? = null + private var rotation = 0 + private var _anchorU = 0.5f + private var _anchorV = 1f + private val background: BubbleDrawable = BubbleDrawable(context) + + init { + textView = rotationLayout.findViewById(R.id.amu_text) + contentView = textView + setStyle(STYLE_DEFAULT) + } + + /** + * Sets the text content, then creates an icon with the current style. + * + * @param text the text content to display inside the icon. + */ + fun makeIcon(text: CharSequence?): Bitmap { + textView?.text = text + return makeIcon() + } + + /** + * Creates an icon with the current content and style. + * + * + * This method is useful if a custom view has previously been set, or if text content is not + * applicable. + */ + fun makeIcon(): Bitmap { + val measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) + container.measure(measureSpec, measureSpec) + var measuredWidth = container.measuredWidth + var measuredHeight = container.measuredHeight + container.layout(0, 0, measuredWidth, measuredHeight) + if (rotation == 1 || rotation == 3) { + measuredHeight = container.measuredWidth + measuredWidth = container.measuredHeight + } + val r = createBitmap(measuredWidth, measuredHeight) + r.eraseColor(Color.TRANSPARENT) + val canvas = Canvas(r) + when (rotation) { + 1 -> { + canvas.translate(measuredWidth.toFloat(), 0f) + canvas.rotate(90f) + } + 2 -> canvas.rotate(180f, (measuredWidth / 2).toFloat(), (measuredHeight / 2).toFloat()) + 3 -> { + canvas.translate(0f, measuredHeight.toFloat()) + canvas.rotate(270f) + } + } + container.draw(canvas) + return r + } + + /** + * Sets the child view for the icon. + * + * + * If the view contains a [TextView] with the id "text", operations such as [.setTextAppearance] and [.makeIcon] will operate upon that [TextView]. + */ + fun setContentView(contentView: View) { + rotationLayout.removeAllViews() + rotationLayout.addView(contentView) + this.contentView = contentView + val view = rotationLayout.findViewById(R.id.amu_text) + textView = if (view is TextView) view else null + } + + /** + * Rotates the contents of the icon. + * + * @param degrees the amount the contents should be rotated, as a multiple of 90 degrees. + */ + fun setContentRotation(degrees: Int) { + rotationLayout.setViewRotation(degrees) + } + + /** + * Rotates the icon. + * + * @param degrees the amount the icon should be rotated, as a multiple of 90 degrees. + */ + fun setRotation(degrees: Int) { + rotation = (degrees + 360) % 360 / 90 + } + + /** + * @return u coordinate of the anchor, with rotation applied. + */ + fun getAnchorU(): Float { + return rotateAnchor(_anchorU, _anchorV) + } + + /** + * @return v coordinate of the anchor, with rotation applied. + */ + fun getAnchorV(): Float { + return rotateAnchor(_anchorV, _anchorU) + } + + /** + * Rotates the anchor around (u, v) = (0, 0). + */ + private fun rotateAnchor(u: Float, v: Float): Float { + return when (rotation) { + 0 -> u + 1 -> 1 - v + 2 -> 1 - u + 3 -> v + else -> throw IllegalStateException() + } + } + + /** + * Sets the text color, size, style, hint color, and highlight color from the specified + * `TextAppearance` resource. + * + * @param resid the identifier of the resource. + */ + fun setTextAppearance(context: Context, resid: Int) { + textView?.setTextAppearance(context, resid) + } + + /** + * Sets the text color, size, style, hint color, and highlight color from the specified + * `TextAppearance` resource. + * + * @param resid the identifier of the resource. + */ + fun setTextAppearance(resid: Int) { + setTextAppearance(context, resid) + } + + /** + * Sets the style of the icon. The style consists of a background and text appearance. + */ + fun setStyle(style: Int) { + setColor(getStyleColor(style)) + setTextAppearance(context, getTextStyle(style)) + } + + /** + * Sets the background to the default, with a given color tint. + * + * @param color the color for the background tint. + */ + fun setColor(color: Int) { + background.color = color + setBackground(background) + } + + /** + * Set the background to a given Drawable, or remove the background. + * + * @param background the Drawable to use as the background, or null to remove the background. + */ + fun setBackground(background: Drawable?) { + container.background = background + + // Force setting of padding. + // setBackgroundDrawable does not call setPadding if the background has 0 padding. + if (background != null) { + val rect = Rect() + background.getPadding(rect) + container.setPadding(rect.left, rect.top, rect.right, rect.bottom) + } else { + container.setPadding(0, 0, 0, 0) + } + } + + /** + * Sets the padding of the content view. The default padding of the content view (i.e. text + * view) is 5dp top/bottom and 10dp left/right. + * + * @param left the left padding in pixels. + * @param top the top padding in pixels. + * @param right the right padding in pixels. + * @param bottom the bottom padding in pixels. + */ + fun setContentPadding(left: Int, top: Int, right: Int, bottom: Int) { + contentView?.setPadding(left, top, right, bottom) + } + + companion object { + const val STYLE_DEFAULT = 1 + const val STYLE_WHITE = 2 + const val STYLE_RED = 3 + const val STYLE_BLUE = 4 + const val STYLE_GREEN = 5 + const val STYLE_PURPLE = 6 + const val STYLE_ORANGE = 7 + private fun getStyleColor(style: Int): Int { + return when (style) { + STYLE_RED -> -0x33ff01 + STYLE_BLUE -> -0xff6634 + STYLE_GREEN -> -0x996700 + STYLE_PURPLE -> -0x66cce7 + STYLE_ORANGE -> -0x7800 + STYLE_DEFAULT, STYLE_WHITE -> -0x1 + else -> -0x1 + } + } + + private fun getTextStyle(style: Int): Int { + return when (style) { + STYLE_RED, STYLE_BLUE, STYLE_GREEN, STYLE_PURPLE, STYLE_ORANGE -> R.style.amu_Bubble_TextAppearance_Light + STYLE_DEFAULT, STYLE_WHITE -> R.style.amu_Bubble_TextAppearance_Dark + else -> R.style.amu_Bubble_TextAppearance_Dark + } + } + } +} \ No newline at end of file diff --git a/library/src/main/java/com/google/maps/android/ui/RotationLayout.java b/library/src/main/java/com/google/maps/android/ui/RotationLayout.java deleted file mode 100644 index f5f8537ac..000000000 --- a/library/src/main/java/com/google/maps/android/ui/RotationLayout.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2013 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 com.google.maps.android.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.widget.FrameLayout; - -/** - * RotationLayout rotates the contents of the layout by multiples of 90 degrees. - *

- * May not work with padding. - */ -public class RotationLayout extends FrameLayout { - private int mRotation; - - public RotationLayout(Context context) { - super(context); - } - - public RotationLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public RotationLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mRotation == 1 || mRotation == 3) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); - } else { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - /** - * @param degrees the rotation, in degrees. - */ - public void setViewRotation(int degrees) { - mRotation = ((degrees + 360) % 360) / 90; - } - - - @Override - public void dispatchDraw(Canvas canvas) { - if (mRotation == 0) { - super.dispatchDraw(canvas); - return; - } - - if (mRotation == 1) { - canvas.translate(getWidth(), 0); - canvas.rotate(90, getWidth() / 2, 0); - canvas.translate(getHeight() / 2, getWidth() / 2); - } else if (mRotation == 2) { - canvas.rotate(180, getWidth() / 2, getHeight() / 2); - } else { - canvas.translate(0, getHeight()); - canvas.rotate(270, getWidth() / 2, 0); - canvas.translate(getHeight() / 2, -getWidth() / 2); - } - - super.dispatchDraw(canvas); - } -} diff --git a/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt b/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt new file mode 100644 index 000000000..48992ed56 --- /dev/null +++ b/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt @@ -0,0 +1,74 @@ +/* + * Copyright 2013 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 com.google.maps.android.ui + +import android.content.Context +import android.graphics.Canvas +import android.util.AttributeSet +import android.widget.FrameLayout + +/** + * RotationLayout rotates the contents of the layout by multiples of 90 degrees. + * + * + * May not work with padding. + */ +class RotationLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0 +) : FrameLayout(context, attrs, defStyle) { + private var rotation = 0 + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + if (rotation == 1 || rotation == 3) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + setMeasuredDimension(measuredHeight, measuredWidth) + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + } + } + + /** + * @param degrees the rotation, in degrees. + */ + fun setViewRotation(degrees: Int) { + rotation = (degrees + 360) % 360 / 90 + } + + override fun dispatchDraw(canvas: Canvas) { + when (rotation) { + 0 -> super.dispatchDraw(canvas) + 1 -> { + canvas.translate(width.toFloat(), 0f) + canvas.rotate(90f, width / 2f, 0f) + canvas.translate(height / 2f, width / 2f) + super.dispatchDraw(canvas) + } + 2 -> { + canvas.rotate(180f, width / 2f, height / 2f) + super.dispatchDraw(canvas) + } + 3 -> { + canvas.translate(0f, height.toFloat()) + canvas.rotate(270f, width / 2f, 0f) + canvas.translate(height / 2f, -width / 2f) + super.dispatchDraw(canvas) + } + } + } +} \ No newline at end of file diff --git a/library/src/main/java/com/google/maps/android/ui/SquareTextView.java b/library/src/main/java/com/google/maps/android/ui/SquareTextView.java deleted file mode 100644 index 20df4a9d2..000000000 --- a/library/src/main/java/com/google/maps/android/ui/SquareTextView.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2013 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 com.google.maps.android.ui; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.widget.TextView; - -/** - * This class is extending from TextView to avoid introducing App Compat dependencies. Android Studio might show an error here or - * not, depending on the Inspection Settings. It's not really an error, just a warning. - * - */ -@SuppressLint("AppCompatCustomView") -public class SquareTextView extends TextView { - private int mOffsetTop = 0; - private int mOffsetLeft = 0; - - public SquareTextView(Context context) { - super(context); - } - - public SquareTextView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public SquareTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - int width = getMeasuredWidth(); - int height = getMeasuredHeight(); - int dimension = Math.max(width, height); - if (width > height) { - mOffsetTop = width - height; - mOffsetLeft = 0; - } else { - mOffsetTop = 0; - mOffsetLeft = height - width; - } - setMeasuredDimension(dimension, dimension); - } - - @Override - public void draw(Canvas canvas) { - canvas.translate(mOffsetLeft / 2, mOffsetTop / 2); - super.draw(canvas); - } -} diff --git a/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt b/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt new file mode 100644 index 000000000..3067a7d40 --- /dev/null +++ b/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2013 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 com.google.maps.android.ui + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Canvas +import android.util.AttributeSet +import android.widget.TextView +import kotlin.math.max + +/** + * This class is extending from TextView to avoid introducing App Compat dependencies. Android Studio might show an error here or + * not, depending on the Inspection Settings. It's not really an error, just a warning. + * + */ +@SuppressLint("AppCompatCustomView") +class SquareTextView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0 +) : TextView(context, attrs, defStyle) { + private var mOffsetTop = 0 + private var mOffsetLeft = 0 + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val width = measuredWidth + val height = measuredHeight + val dimension = max(width, height) + if (width > height) { + mOffsetTop = width - height + mOffsetLeft = 0 + } else { + mOffsetTop = 0 + mOffsetLeft = height - width + } + setMeasuredDimension(dimension, dimension) + } + + override fun draw(canvas: Canvas) { + canvas.translate(mOffsetLeft / 2f, mOffsetTop / 2f) + super.draw(canvas) + } +} \ No newline at end of file diff --git a/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt b/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt new file mode 100644 index 000000000..301a2657c --- /dev/null +++ b/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt @@ -0,0 +1,67 @@ +package com.google.maps.android.ui + +import android.content.Context +import android.graphics.Bitmap +import android.widget.TextView +import androidx.test.core.app.ApplicationProvider +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class IconGeneratorTest { + + private lateinit var iconGenerator: IconGenerator + private lateinit var context: Context + + @Before + fun setUp() { + context = ApplicationProvider.getApplicationContext() + iconGenerator = IconGenerator(context) + } + + @Test + fun testMakeIcon() { + val icon = iconGenerator.makeIcon("Test") + assertThat(icon).isNotNull() + assertThat(icon.width).isGreaterThan(0) + assertThat(icon.height).isGreaterThan(0) + } + + @Test + fun testSetContentView() { + val textView = TextView(context) + textView.text = "Custom View" + iconGenerator.setContentView(textView) + val icon: Bitmap = iconGenerator.makeIcon() + assertThat(icon).isNotNull() + assertThat(icon.width).isGreaterThan(0) + assertThat(icon.height).isGreaterThan(0) + } + + @Test + fun testSetRotation() { + iconGenerator.setRotation(90) + assertThat(iconGenerator.getAnchorU()).isWithin(1e-6f).of(0.0f) + assertThat(iconGenerator.getAnchorV()).isWithin(1e-6f).of(0.5f) + val icon = iconGenerator.makeIcon("Rotated") + assertThat(icon).isNotNull() + } + + @Test + fun testSetContentRotation() { + iconGenerator.setContentRotation(90) + val icon = iconGenerator.makeIcon("Content Rotated") + assertThat(icon).isNotNull() + } + + @Test + fun testSetStyle() { + iconGenerator.setStyle(IconGenerator.STYLE_RED) + // Hard to test the color, but we can check that it doesn't crash + val icon = iconGenerator.makeIcon("Styled") + assertThat(icon).isNotNull() + } +} \ No newline at end of file From a6c7ab8fbbc88e5a4fe770dee27a43869eaf1f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Fri, 29 Aug 2025 14:23:00 +0200 Subject: [PATCH 2/4] build: header --- .../src/main/java/com/google/maps/android/ui/AnimationUtil.kt | 2 +- .../src/main/java/com/google/maps/android/ui/BubbleDrawable.kt | 2 +- .../src/main/java/com/google/maps/android/ui/IconGenerator.kt | 2 +- .../src/main/java/com/google/maps/android/ui/RotationLayout.kt | 2 +- .../src/main/java/com/google/maps/android/ui/SquareTextView.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt b/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt index e6364e7c2..ca5a17665 100644 --- a/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt +++ b/library/src/main/java/com/google/maps/android/ui/AnimationUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google Inc. + * Copyright 2025 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt b/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt index c5686b830..96ed6095c 100644 --- a/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt +++ b/library/src/main/java/com/google/maps/android/ui/BubbleDrawable.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google Inc. + * Copyright 2025 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt b/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt index 9dbf38615..0149b4051 100644 --- a/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt +++ b/library/src/main/java/com/google/maps/android/ui/IconGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2013 Google Inc. + * Copyright 2025 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt b/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt index 48992ed56..3a244cc1b 100644 --- a/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt +++ b/library/src/main/java/com/google/maps/android/ui/RotationLayout.kt @@ -1,5 +1,5 @@ /* - * Copyright 2013 Google Inc. + * Copyright 2025 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt b/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt index 3067a7d40..15850d3c4 100644 --- a/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt +++ b/library/src/main/java/com/google/maps/android/ui/SquareTextView.kt @@ -1,5 +1,5 @@ /* - * Copyright 2013 Google Inc. + * Copyright 2025 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From ff3c13d342f2a77f98fca1e4a4f70d12f9f6a933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Fri, 29 Aug 2025 14:24:58 +0200 Subject: [PATCH 3/4] Stop tracking multi_profile_two.xml --- .../src/main/res/layout/multi_profile_two.xml | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 demo/src/main/res/layout/multi_profile_two.xml diff --git a/demo/src/main/res/layout/multi_profile_two.xml b/demo/src/main/res/layout/multi_profile_two.xml deleted file mode 100644 index f90804dc0..000000000 --- a/demo/src/main/res/layout/multi_profile_two.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - From 624123a344ee808ee1ebf6b4ed4bff519d604e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Fri, 29 Aug 2025 14:26:08 +0200 Subject: [PATCH 4/4] build: header --- .../google/maps/android/ui/IconGeneratorTest.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt b/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt index 301a2657c..ea447845d 100644 --- a/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt +++ b/library/src/test/java/com/google/maps/android/ui/IconGeneratorTest.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2025 Google LLC + * + * 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 com.google.maps.android.ui import android.content.Context