如何在 canvas 圈子中设置图像视图或图标?

how is possible to set imageview or icon in the canvas circle?

如何在 canvas 圈子中设置图像或图标?我有一个自定义 canvas 视图,通过在地图上移动相机,调整大小方法将被激活并改变视图的形状,通过停止地图的移动,它将像出厂设置一样...快乐英语:- ))))

public class CancvasCircle extends androidx.appcompat.widget.AppCompatImageView {
  ///main circle  resize fields
  public static final int MAIN_CIRCLE_PRE_RADIUS = 40;
  public static final int MAIN_CIRCLE_POST_RADIUS = 43;
  public static final String MAIN_CIRCLE_PRE_STROKE_COLOR = "#69DAE2";
  //4CEAE3
  public static final String MAIN_CIRCLE_POST_STROKE_COLOR = "#FBCC38";
  ///// line resize fields
  public static final int LINE_HIEGHT_STOP = 45;
  public static final int LINE_HIEGHT_START_PRE = 0;
  public static final int LINE_HIEGHT_START_POST = 23;
  public static final int SHADOW_CIRCLE_PRE_RADIUS = 15;

  //circle paint fields
  Paint strokeCircle;
  Paint fillCircle;
  Paint shadowCircle;
  Paint line;
  Paint dot;

  //center
  float centerX;
  float centerY;

  //main circle fields
  private int radiusMain = MAIN_CIRCLE_PRE_RADIUS;
  private String colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;

  //line fields
  private float lineStartY;
  private float lineStopY;
  //shadow circle fields
  private int shadowRadius = SHADOW_CIRCLE_PRE_RADIUS;

  public CancvasCircle(Context context) {
    super(context);
    init();
  }

  public CancvasCircle(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  public CancvasCircle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }

  public void init() {

    strokeCircle = new Paint();
    strokeCircle.setAntiAlias(true);
    strokeCircle.setAntiAlias(true);
    strokeCircle.setStrokeWidth(10);
    strokeCircle.setStyle(Paint.Style.STROKE);

    fillCircle = new Paint();
    fillCircle.setAntiAlias(true);
    fillCircle.setColor(Color.parseColor("#BEC6CC"));
    fillCircle.setStyle(Paint.Style.FILL);

    shadowCircle = new Paint();
    shadowCircle.setAntiAlias(true);
    shadowCircle.setColor(Color.parseColor("#1f000000"));
    shadowCircle.setStyle(Paint.Style.FILL);

    line = new Paint();
    line.setAntiAlias(true);
    line.setColor(Color.parseColor("#000000"));
    line.setStrokeWidth(4);
    line.setStyle(Paint.Style.FILL);

    dot = new Paint();
    dot.setAntiAlias(true);
    dot.setColor(Color.parseColor("#000000"));
    dot.setStrokeWidth(4);
    dot.setStyle(Paint.Style.FILL);
  }

  public void resizeStrokeCircleParams(Boolean resize) {
    if (resize) {
      this.radiusMain = MAIN_CIRCLE_POST_RADIUS;
      this.colorMain = MAIN_CIRCLE_POST_STROKE_COLOR;
      this.lineStartY = centerY - LINE_HIEGHT_START_POST;
      this.lineStopY = LINE_HIEGHT_STOP + LINE_HIEGHT_START_POST - 10;
      this.shadowRadius =  LINE_HIEGHT_START_POST;

    } else {
      this.radiusMain = MAIN_CIRCLE_PRE_RADIUS;
      this.colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;
      this.lineStartY = centerY - LINE_HIEGHT_START_PRE;
      this.lineStopY = LINE_HIEGHT_STOP;
      this.shadowRadius = SHADOW_CIRCLE_PRE_RADIUS;
    }
    invalidate();
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    centerX = getWidth() / 2f;
    centerY = getHeight() / 2f;
    int radius = radiusMain;
    float lineStopY = this.lineStopY;
    float lineStartY = this.lineStartY;
    int shadowRadius = this.shadowRadius;

    strokeCircle.setColor(Color.parseColor(colorMain));


    canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, strokeCircle);
    canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, fillCircle);
    canvas.drawCircle(centerX, centerY, shadowRadius, shadowCircle);
    canvas.drawLine(centerX, lineStartY, centerX, centerY - lineStopY, line);
    canvas.drawPoint(centerX,centerY,dot);
  }
}

里面可以像硬币一样翻转两张图片吗????

查看示例作为自定义视图。

public class ViewCircle extends View{
    final Bitmap bms; //source
    final Bitmap bmm; //mask
    final Paint paint;

    public ViewCircle( Context context ){
        super( context );
        bms = BitmapFactory.decodeResource( getResources(), R.drawable.pr_0000 );
        bmm = Bitmap.createBitmap( bms.getWidth(), bms.getHeight(), Bitmap.Config.ARGB_8888 );
        Canvas canvas = new Canvas( bmm );
        paint = new Paint( Paint.ANTI_ALIAS_FLAG );
        canvas.drawCircle( bmm.getWidth()/2, bmm.getHeight()/2, Math.min(bmm.getWidth()/2,bmm.getHeight()/2), paint );
        paint.setXfermode( new PorterDuffXfermode( PorterDuff.Mode.SRC_IN ) );
        canvas.drawBitmap( bms, 0, 0, paint );
    }
    @Override
    protected void onDraw( Canvas canvas ){
        super.onDraw( canvas );
        canvas.drawBitmap( bms, 0,0, null );
        canvas.drawBitmap( bmm, bms.getWidth(),0, null );
    }
}

我使用此方法从 XML 布局创建位图并在我的代码中设置它...

  public Bitmap getMarkerBitmapFromView(@DrawableRes int resIdMain, @DrawableRes int resId) {

    View customMarkerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_marker, null);
    customMarkerView.findViewById(R.id.custom_marker_firstlayout);
    if(resIdMain != 0){

      customMarkerView.setBackgroundResource(resIdMain);
    }
    ImageView markerImageView = (ImageView) customMarkerView.findViewById(R.id.custom_marker_secondLayout);
    if(resId != 0){
      markerImageView.setImageResource(resId);
    }
    customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
    customMarkerView.buildDrawingCache();
    Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(),
      Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(returnedBitmap);
    canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
    Drawable drawable = customMarkerView.getBackground();
    if (drawable != null)
      drawable.draw(canvas);
    customMarkerView.draw(canvas);
    return returnedBitmap;
  }

并在 onDraw() 中将其设置在我的 canvas 视图中并将其设置在我的圆圈中间:

canvas.drawBitmap(getMarkerBitmapFromView(0,guildMarkerICON),convertDpToPixel(76,context),imageHieght,null);

因为在不同的设备上画错了我用这个方法来改变像素和dp:

  public static float convertPixelsToDp(float px,Context context){
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return dp;
  }

  public static float convertDpToPixel(float dp,Context context){
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    float px = dp * (metrics.densityDpi/160f);
    return px;
  }

和 XML 提供我的位图(你可以使用图像或任何你想要的东西)的布局是 (custom_marker.xml) :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/custom_marker_firstlayout"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:background="@drawable/center_marker_background">

  <ImageView
    android:id="@+id/custom_marker_secondLayout"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_gravity="center"
    android:contentDescription="@null"
    />
</FrameLayout>

当你想改变标记时使用这个方法(比如移动地图):

map.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
  @Override
  public void onCameraMoveStarted(int i) {
    canvasView.resizeStrokeCircleParams(true,guildMarkerICON);
  }
});



map.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
      @Override
      public void onCameraIdle() {
        canvasView.resizeStrokeCircleParams(false,guildMarkerICON);
      }
    });

最后这是我使用的自定义 canvas class,我通过调整大小方法将自定义图标传递给它并根据需要进行设置...享受它:

public class CancvasCircle extends androidx.appcompat.widget.AppCompatImageView {
  ///main circle  resize fields
  public static final int MAIN_CIRCLE_PRE_RADIUS = 24;
  public static final int MAIN_CIRCLE_POST_RADIUS = 26;

  public static final String MAIN_CIRCLE_PRE_STROKE_COLOR = "#F44336";

  public static final String MAIN_CIRCLE_POST_STROKE_COLOR = "#FFCC59";
  //FFCC59
  //FBCC38
  ///// line resize fields
  public static final int LINE_HIEGHT_STOP = 24;
  public static final int LINE_HIEGHT_START_PRE = 0;
  public static final int LINE_HIEGHT_START_POST = 11;
  public static final int SHADOW_CIRCLE_PRE_RADIUS = 14;

  private final Context context;

  /// image view fields



  //circle paint fields
  Paint strokeCircle;
  Paint fillCircle;
  Paint shadowCircle;
  Paint line;
  Paint dot;
  Paint  imagePaint;

  //center
  float centerX;
  float centerY;

  //main circle fields
  private int radiusMain = MAIN_CIRCLE_PRE_RADIUS;
  private String colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;

  //line fieldsاذغ
  private float lineStartY;
  private float lineStopY;
  //shadow circle fields
  private int shadowRadius = SHADOW_CIRCLE_PRE_RADIUS;
  private Bitmap canvasBitmap;
  private int imageTopPadding;
  private int guildMarkerICON
    ;


  public CancvasCircle(Context context) {
    super(context);
    this.context = context;
    init();
  }

  public CancvasCircle(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    init();
  }

  public CancvasCircle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this.context = context;
    init();
  }

  public void init() {


    strokeCircle = new Paint();
    strokeCircle.setAntiAlias(true);
    strokeCircle.setAntiAlias(true);
    strokeCircle.setStrokeWidth(12);
    strokeCircle.setStyle(Paint.Style.STROKE);

    fillCircle = new Paint();
    fillCircle.setAntiAlias(true);
    fillCircle.setColor(Color.parseColor("#af283232"));
    fillCircle.setStyle(Paint.Style.FILL);

    shadowCircle = new Paint();
    shadowCircle.setAntiAlias(true);
    shadowCircle.setColor(Color.parseColor("#1f000000"));
    shadowCircle.setStyle(Paint.Style.FILL);

    line = new Paint();
    line.setAntiAlias(true);
    line.setColor(Color.parseColor("#000000"));
    line.setStrokeWidth(4);
    line.setStyle(Paint.Style.FILL);

    dot = new Paint();
    dot.setAntiAlias(true);
    dot.setColor(Color.parseColor("#000000"));
    dot.setStrokeWidth(4);
    dot.setStyle(Paint.Style.FILL);


  }

  public void resizeStrokeCircleParams(Boolean resize , int guildMarkerICON) {
    this.guildMarkerICON  = guildMarkerICON;
    if (resize) {
      this.radiusMain = (int) convertDpToPixel(MAIN_CIRCLE_POST_RADIUS,context);
      this.colorMain = MAIN_CIRCLE_POST_STROKE_COLOR;
      this.lineStartY = centerY -convertDpToPixel( LINE_HIEGHT_START_POST,context);
      this.lineStopY =convertDpToPixel( LINE_HIEGHT_STOP,context) + convertDpToPixel(LINE_HIEGHT_START_POST,context) -8;
      this.shadowRadius = (int) convertDpToPixel(LINE_HIEGHT_START_POST,context);
      this.imageTopPadding = (int) convertDpToPixel(19,context);

    } else {
      this.radiusMain = (int) convertDpToPixel( MAIN_CIRCLE_PRE_RADIUS,context);
      this.colorMain = MAIN_CIRCLE_PRE_STROKE_COLOR;
      this.lineStartY = centerY - convertDpToPixel(LINE_HIEGHT_START_PRE,context);
      this.lineStopY = convertDpToPixel(LINE_HIEGHT_STOP,context);
      this.shadowRadius = (int) convertDpToPixel(SHADOW_CIRCLE_PRE_RADIUS,context);
      this.imageTopPadding = (int) convertDpToPixel( 28,context);


    }

  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);


    centerX = getWidth() / 2f;
    centerY = getHeight() / 2f;
    int radius = radiusMain;
    float lineStopY = this.lineStopY;
    float lineStartY = this.lineStartY;
    int shadowRadius = this.shadowRadius;
    int imageHieght = this.imageTopPadding;

    strokeCircle.setColor(Color.parseColor(colorMain));



    // if map is moving  (imageHieght == 41)
    // if map is not moving (imageHieght == 56)


    canvas.drawLine(centerX, lineStartY, centerX, centerY - lineStopY, line);
    canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, strokeCircle);
    canvas.drawCircle(centerX, centerY - lineStopY - radius, radius, fillCircle);
    canvas.drawCircle(centerX, centerY, shadowRadius, shadowCircle);
    canvas.drawPoint(centerX,centerY,dot);

    canvas.drawBitmap(getMarkerBitmapFromView(0,guildMarkerICON),convertDpToPixel(76,context),imageHieght,null);
invalidate();
  }







  public static float convertPixelsToDp(float px,Context context){

    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return dp;

  }







  public static float convertDpToPixel(float dp,Context context){

    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    float px = dp * (metrics.densityDpi/160f);
    return px;

  }




  public Bitmap getMarkerBitmapFromView(@DrawableRes int resIdMain, @DrawableRes int resId) {

    View customMarkerView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom_marker, null);
    customMarkerView.findViewById(R.id.custom_marker_firstlayout);
    if(resIdMain != 0){

      customMarkerView.setBackgroundResource(resIdMain);
    }
    ImageView markerImageView = (ImageView) customMarkerView.findViewById(R.id.custom_marker_secondLayout);
    if(resId != 0){
      markerImageView.setImageResource(resId);
    }
    customMarkerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    customMarkerView.layout(0, 0, customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight());
    customMarkerView.buildDrawingCache();
    Bitmap returnedBitmap = Bitmap.createBitmap(customMarkerView.getMeasuredWidth(), customMarkerView.getMeasuredHeight(),
      Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(returnedBitmap);
    canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
    Drawable drawable = customMarkerView.getBackground();
    if (drawable != null)
      drawable.draw(canvas);
    customMarkerView.draw(canvas);
    return returnedBitmap;
  }

}

结果: