【问题标题】:Is there a way to implement rounded corners to a Mapfragment?有没有办法为 Mapfragment 实现圆角?
【发布时间】:2013-01-06 07:29:29
【问题描述】:

我想给地图一个好看的圆角,因为它下面的两个框有。 我不能用它自己的地图片段来做,因为没有背景属性 分段。 将地图设置在布局内并将其背景设置为圆形对我没有帮助 也是,结果如下:

我可以合并地图,但这会使地图变小,我想避免它。

编辑: @Ryan 这是新结果 #2:

我想这还不错,甚至没有靠近其他盒子的角落, 但仍然不错,多做一点工作可能会接近我只是没有普通的图像编辑器。 但现在仍然困扰我的一件事是“位置”文本视图和它自己的地图之间的分离。我可以用其他方式画补丁,以便现在有距离吗?我就是这样做的:

好吧,我终于想通了:

这是我用于补丁的:

谢谢。

【问题讨论】:

    标签: android android-layout android-maps-v2


    【解决方案1】:

    我知道这是一篇旧帖子,但您可以尝试像这样使用卡片:

    <android.support.v7.widget.CardView
        android:layout_width="300dp"
        android:layout_height="350dp"
        android:layout_gravity="center_horizontal|center_vertical"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="20dp"
        app:cardCornerRadius="12dp"
        app:cardElevation="12dp">
    
        <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </android.support.v7.widget.CardView>
    

    【讨论】:

    • 今天确实可以使用卡片来做到这一点。当被问到这个问题时,卡片还不存在。很好的答案。
    【解决方案2】:

    我还没有尝试过,但我会在 mapView / mapFragment 的顶部放置一个带有圆角和透明中间的视图。

    即把mapFragment和圆角视图放在一个FrameLayout中,同时填充FrameLayout,然后让圆角视图的中间部分透明。

    为了进一步说明,您可以在布局中进行如下操作:-

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <fragment
        xmlns:map="http://schemas.android.com/apk/res-auto"
        android:id="@+id/mapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.MapFragment" />
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/rounded_background"
        android:orientation="vertical" >
    </LinearLayout>
    
    </FrameLayout>
    

    rounded_background 是一个带有圆角和透明中间的 9-patch。例如

    希望对你有帮助,

    瑞恩

    【讨论】:

    • 放置视图是什么意思?什么样的看法?以及如何使其中间透明?
    • 我只是做了一个非常粗略的 9 补丁来给你这个想法,并不打算让你按原样使用它;-) 如果你制作了一个像样的资产,它看起来会很好。
    • 另外你需要把它当作九个补丁使用,重命名为filename.9.png。更多信息请参见radleymarx.com/blog/simple-guide-to-9-patch
    • 好吧,我尝试这样做,但我很想知道是否有另一种方法来处理这个问题,你用什么软件来创建那些 9 补丁?
    • 一直没搞懂这个工具怎么用,有没有其他办法?
    【解决方案3】:

    最简单的方法是将地图片段与 ImageView 一起包装在 FrameLayout 中。 Imageview 将在地图片段的顶部显示一个圆角矩形。在最简单的形式中,您将看到圆角矩形内的地图片段,其角伸出圆角矩形,因为地图视图本身不是圆角的。为了克服这种视觉上的怪异,只需在地图片段上应用 layout_margin 值。该值应等于矩形的边框宽度。

       <FrameLayout
        android:id="@+id/map_container"
        android:layout_width="wrap_content"
        android:layout_height="340dp" >
    
        <fragment
            android:id="@+id/map"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="3dp"
            android:name="com.google.android.gms.maps.SupportMapFragment"/>
    
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/map_bg_box" />
    
    </FrameLayout>
    

    矩形drawable被定义为如下的xml形状

    <?xml version="1.0" encoding="UTF-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
    
        <stroke android:width="3dp"
        android:color="#ff000000" />
    
        <corners android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
        android:topLeftRadius="7dp" android:topRightRadius="7dp"/>
    
    </shape>
    

    请注意,矩形的笔触宽度为 3dp,这与我们应用于地图片段的 layout_margin 属性的值完全相同。结果是一个漂亮的圆角地图片段,如下面的屏幕截图所示

    【讨论】:

    • 这对我不起作用。我尝试了所有方法,但没有成功。
    • 按照这里描述的解决方案,你得到了什么结果?
    • 地图角与黑色圆形重叠:S地图超出形状。
    • @KinGPinG 你确定按照正确的顺序放置形状吗?
    【解决方案4】:

    在此布局中包装地图片段:

    package com.example.yourpackage;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.widget.RelativeLayout;
    
    /**
     * Just extend any Layout you like/need
     */
    public class RoundedLayout extends RelativeLayout {
    
    private Path mPathCorners = new Path();
    private Path mPathCircle = new Path();
    private float mCornerRadius;
    
    /**
     * border path
     */
    private Path mPathCornersBorder = new Path();
    private Path mPathCircleBorder = new Path();
    private int mBorderWidth = 0;
    private int mBorderHalf;
    private boolean mShowBorder = false;
    private int mBorderColor = 0xFFFF7700;
    
    private float mDensity = 1.0f;
    
    /**
     * Rounded corners or circle shape
     */
    private boolean mIsCircleShape = false;
    
    private Paint mPaint = new Paint();
    
    private float dpFromPx(final float px) {
        return px / mDensity;
    }
    
    private float pxFromDp(final float dp) {
        return dp * mDensity;
    }
    
    public RoundedLayout(Context context) {
        this(context, null);
    }
    
    public RoundedLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    
    public RoundedLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mDensity = getResources().getDisplayMetrics().density;
        // just a default for corner radius
        mCornerRadius = pxFromDp(25f);
    
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mBorderColor);
        setBorderWidth(Math.round(pxFromDp(2f)));
    }
    
    /**
     * Switch to circle or rectangle shape
     *
     * @param useCircle
     */
    public void setShapeCircle(boolean useCircle) {
        mIsCircleShape = useCircle;
        invalidate();
    }
    
    /**
     * change corner radius
     *
     * @param radius
     */
    public void setCornerRadius(int radius) {
        mCornerRadius = radius;
        invalidate();
    }
    
    public void showBorder(boolean show) {
        mShowBorder = show;
        invalidate();
    }
    
    public void setBorderWidth(int width) {
        mBorderWidth = width;
        mBorderHalf = Math.round(mBorderWidth / 2);
        if (mBorderHalf == 0) {
            mBorderHalf = 1;
        }
    
        mPaint.setStrokeWidth(mBorderWidth);
        updateCircleBorder();
        updateRectangleBorder();
        invalidate();
    }
    
    public void setBorderColor(int color) {
        mBorderColor = color;
        mPaint.setColor(color);
        invalidate();
    }
    
    // helper reusable vars, just IGNORE
    private float halfWidth, halfHeight, centerX, centerY;
    private RectF rect = new RectF(0, 0, 0, 0);
    private RectF rectBorder = new RectF(0, 0, 0, 0);
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    
        // just calculate both shapes, is not heavy
    
        // rounded corners path
        rect.left = 0;
        rect.top = 0;
        rect.right = w;
        rect.bottom = h;
        mPathCorners.reset();
        mPathCorners.addRoundRect(rect, mCornerRadius, mCornerRadius, Path.Direction.CW);
        mPathCorners.close();
    
        // circle path
        halfWidth = w / 2f;
        halfHeight = h / 2f;
        centerX = halfWidth;
        centerY = halfHeight;
        mPathCircle.reset();
        mPathCircle.addCircle(centerX, centerY, Math.min(halfWidth, halfHeight), Path.Direction.CW);
        mPathCircle.close();
    
        updateRectangleBorder();
        updateCircleBorder();
    }
    
    // helper reusable var, just IGNORE
    private int save;
    
    @Override
    protected void dispatchDraw(Canvas canvas) {
        save = canvas.save();
        canvas.clipPath(mIsCircleShape ? mPathCircle : mPathCorners);
        super.dispatchDraw(canvas);
        canvas.restoreToCount(save);
    
        if (mShowBorder) {
            canvas.drawPath(mIsCircleShape ? mPathCircleBorder : mPathCornersBorder, mPaint);
        }
    }
    
    private void updateCircleBorder() {
        // border path for circle
        mPathCircleBorder.reset();
        mPathCircleBorder.addCircle(centerX, centerY, Math.min(halfWidth - mBorderHalf,
                halfHeight - mBorderHalf), Path.Direction.CW);
        mPathCircleBorder.close();
    }
    
    private void updateRectangleBorder() {
        // border path for rectangle
        rectBorder.left = rect.left + mBorderHalf;
        rectBorder.top = rect.top + mBorderHalf;
        rectBorder.right = rect.right - mBorderHalf;
        rectBorder.bottom = rect.bottom - mBorderHalf;
        mPathCornersBorder.reset();
        mPathCornersBorder.addRoundRect(rectBorder, mCornerRadius - mBorderHalf, mCornerRadius -
                mBorderHalf, Path.Direction.CW);
        mPathCornersBorder.close();
    }
    }
    

    在布局中会是这样的:

    <com.example.yourpackage.RoundedLayout
        android:id="@+id/maplayout"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_margin="20dp">
    
        <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            tools:context="com.example.yourpackage.MapsMarkerActivity"/>
    </com.example.yourpackage.RoundedLayout>
    

    在代码中可以是这样的带边框的圆形:

        RoundedLayout rl = (RoundedLayout) findViewById(R.id.maplayout);
        rl.setShapeCircle(true);
        rl.showBorder(true);
        rl.setBorderWidth(2);
    

    此布局可用于塑造任何视图。

    令人难以置信的是,谷歌无法为其 android API 制作有能力(可用)的完整演示。

    【讨论】:

      【解决方案5】:

      对于其他研究此问题的人,我只是使用 GoogleMap.snapshot 解决了这个问题,并使用此堆栈溢出答案来操作位图结果: How to make an ImageView with rounded corners?

      请注意,这仅在您将拥有一个不会与之交互的静态地图时才有效。

      确保在地图加载后拍摄快照。

      我更新了图像视图帮助程序代码以使用路径进行绘制,以支持仅对某些角进行舍入。 IE。如果您只想圆角中的 2 个。

      你只需要使用 float[] 的 path round rect 函数

      我会显示一个进度条,直到我收到来自加载的 GoogleMap 侦听器的回调,而不是拍摄快照。

      如果您过早拍摄快照,您将无法创建宽度和高度为 0 的位图错误。

      希望这有助于在静态地图快照中寻找圆角或其他奇怪形状的人。

      【讨论】:

        【解决方案6】:

        如果您只是尝试以 API 21(Lollipop)和更高版本为目标


        这是最简单的方法。

        parentView.setClipToOutline(true);

        结果

        【讨论】:

        • 什么是'parentView'?我尝试设置 setClipToOutline(true);到实际的 MapFragment,但这对我不起作用...
        • parentView 是 mapFragment 所在的视图。它是其中包含 mapFragment 的视图。
        • 对我不起作用...我用带有圆角背景的 LinearLayout 包裹了地图片段,并调用了 setClipToOutline(true);正如你所建议的。也许它与我使用的主题有关,即“Theme.Translucent.NoTitleBar.Fullscreen”...?
        【解决方案7】:

        在@Nouman_Hanif 发布之后,我最终得到了一个看起来相当不错的解决方案。

        map_rounded_corner_overlay.xml:

        <?xml version="1.0" encoding="UTF-8"?>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
          <stroke android:width="1dp"
                  android:color="@color/white" />
          <corners android:radius="<your_desired_view_corner_radius>"/>
        </shape>
        

        我的地图xml文件:

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
          <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_margin="1dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
          <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/map_rounded_corner_overlay" />
        </RelativeLayout>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-08-10
          • 1970-01-01
          • 2021-04-21
          • 2022-11-15
          • 1970-01-01
          • 2013-07-02
          • 2011-03-12
          相关资源
          最近更新 更多