Android Utility controls Custom lifelike camera aperture view_android

Source: Internet
Author: User
Tags abs diff getcolor gety

Recently mobile phone industry began to popular dual-camera, large aperture function is also used to live. The so-called large aperture function is to be able to focus on the photo later, the principle of its implementation is to get the depth of the picture and focus on the image of infinity through the algorithm to achieve the effect of refocusing.

In a pair of mobile phone's big aperture operation interface has an aperture operation icon, can simulate the aperture adjustment true effect, the feeling is also good, therefore thought realizes this effect. Now I contribute to the implementation of the method, in case your company also want to do dual-camera phone? ( ̄┰ ̄*)

First of all, Baidu the aperture of the picture, observation, you can find that the key is to calculate the different aperture value of each aperture of the position of the blade. For the sake of simplicity, I use the aperture effect of six straight edge blades as an example (other forms, such as seven blades, that is, the position calculation is slightly less convenient, and some arc blades, as long as the blade on both sides of the arc radius is the same line.) Why should the arc radius be the same? Careful observation can be found, adjacent to each other between the two blades to slide, and to maintain the same distance, according to my former primary school geometry division of the experience of the full score can be judged, equal diameter arc is a good drop, other advanced curve can realize the effect, ask the mathematician ( ̄┰ ̄*)! Other parts of the principle are the same).

Make the effect chart:

Let's explain the main contents of this custom view:
1. The realization of this effect is to draw six aperture blades on the hexagonal six corners of the optical circle respectively.
2. Calculate the size of the hexagon according to different aperture values, thus calculating the position of each hexagonal vertex
3. Design blades. Can also let the art mm provide, the program is their own code painting. Note the spacing between the leaves and the angle of each blade is 60°
4. Define custom attributes such as color, spacing, etc.
5. Up and down slide can adjust aperture size
6. To provide the aperture value changes of the Listening interface

Code
Can be downloaded on github:https://github.com/willhua/CameraAperture.git

Package com.example.cameraaperture;
Import Android.content.Context;
Import Android.content.res.TypedArray;
Import Android.graphics.Bitmap;
Import Android.graphics.Bitmap.Config;
Import Android.graphics.Canvas;
Import Android.graphics.Paint;
Import Android.graphics.Path;
Import Android.graphics.PointF;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import android.view.MotionEvent;

Import Android.view.View; /** * up and down can adjust aperture size; * Call Setaperturechangedlistener set aperture value change listener interface; * The maximum diameter of the drawn aperture will fill the view * @author Willhua Http://www.cnblo gs.com/willhua/* */public class Apertureview extends View {public interface aperturechanged {public void OnA
  Perturechanged (float newapert);
  Private static final float rotate_angle = 30;
  private static final String TAG = "Apertureview";
  Private static final float cos_30 = 0.866025f; private static final int WIDTH = 100;
  Measure size when set to wrap_content private static final int HEIGHT = 100;
  private int Mcircleradius; Private INT Mbladecolor;
  private int mbackgroundcolor;
  private int mspace;
  private float Mmaxapert = 1;
  private float Mminapert = 0.2f;

  private float Mcurrentapert = 0.5f; 
  The use of PointF instead of point can reduce the computational error, lest the spacing between the blades due to the calculation error and unbalanced private pointf[] mpoints = new Pointf[6];
  Private Bitmap Mblade;
  Private Paint Mpaint;
  Private Path MPath;

  Private aperturechanged maperturechanged;
  private float Mprevx;

  private float Mprevy;
    Public Apertureview (context, AttributeSet attrs) {Super (context, attrs);
  Init (context, attrs); private void init (context context, AttributeSet attrs) {//Read custom layout properties TypedArray array = Context.obtainstyleda
    Ttributes (Attrs, R.styleable.apertureview);
    Mspace = (int) array.getdimension (r.styleable.apertureview_blade_space, 5);
    Mbladecolor = Array.getcolor (R.styleable.apertureview_blade_color, 0xff000000);
    Mbackgroundcolor = Array.getcolor (R.styleable.apertureview_background_color, 0xFFFFFFFF);
    Array.recycle (); MpaiNT = new Paint (Paint.filter_bitmap_flag |
    Paint.dither_flag);
    Mpaint.setantialias (TRUE);
    for (int i = 0; i < 6; i++) {mpoints[i] = new PointF (); } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (widthmeas
    Urespec, Heightmeasurespec);
    int widthspecmode = Measurespec.getmode (Widthmeasurespec);
    int heightspecmode = Measurespec.getmode (Heightmeasurespec);
    int widthspecsize = measurespec.getsize (Widthmeasurespec);
    int heightspecsize = measurespec.getsize (Heightmeasurespec);
    int paddx = Getpaddingleft () + getpaddingright ();
    int paddY = getpaddingtop () + Getpaddingbottom (); Aperture size to consider minus view padding value Mcircleradius = Widthspecsize-paddx < Heightspecsize-paddy?
    (WIDTHSPECSIZE-PADDX)/2: (Heightspecsize-paddy)/2; Processing if the layout parameter is wrap_content (Widthspecmode = = Measurespec.at_most && Heightspecmode = = Measurespec.at_ MOST) {SetmeasuReddimension (WIDTH, HEIGHT);
    Mcircleradius = (WIDTH-PADDX)/2;
      else if (Widthspecmode = = measurespec.at_most) {setmeasureddimension (WIDTH, heightspecsize); Mcircleradius = Width-paddx < Heightspecsize-paddy?
    (WIDTH-PADDX)/2: (Heightspecsize-paddy)/2;
      else if (Heightspecmode = = measurespec.at_most) {setmeasureddimension (widthspecsize, HEIGHT); Mcircleradius = Widthspecsize-paddx < Height-paddy?
    (WIDTHSPECSIZE-PADDX)/2: (Height-paddy)/2;
    } if (Mcircleradius < 1) {Mcircleradius = 1;
    }//measure to know the size of the aperture you need to draw MPath = new Path ();
    Mpath.addcircle (0, 0, Mcircleradius, Path.Direction.CW);
  Createblade ();
    @Override public void OnDraw (Canvas Canvas) {canvas.save ();
    Calculatepoints ();
    First, pan the Canbvas to the Middle Canvas.translate (getwidth ()/2, GetHeight ()/2); Let the aperture of the blade overall rotation, more fitting actual canvas.rotate (Rotate_angle * (mcurrentapert-mminApert)/(Mmaxapert-mminapert));
    Canvas.clippath (MPath);

    Canvas.drawcolor (Mbackgroundcolor);
      for (int i = 0; i < 6; i++) {canvas.save ();
      Canvas.translate (mpoints[i].x, MPOINTS[I].Y);
      Canvas.rotate (-I * 60);
      Canvas.drawbitmap (mblade, 0, 0, mpaint);
    Canvas.restore ();
  } canvas.restore (); @Override public boolean ontouchevent (Motionevent event) {if (Event.getpointercount () > 1) {return F
    Alse;
      Switch (event.getaction ()) {Case MotionEvent.ACTION_DOWN:mPrevX = Event.getx ();
      Mprevy = Event.gety ();
    Break
      Case MotionEvent.ACTION_MOVE:float DIFFX = Math.Abs ((Event.getx ()-MPREVX));
      float Diffy = Math.Abs (Event.gety ()-Mprevy)); if (Diffy > Diffx) {//vertical sliding float diff = (float) math.sqrt (DIFFX * diffx + diffy * diffy)/MCi
        Rcleradius * Mmaxapert; if (Event.gety () > Mprevy) {//Judgment direction Setcurrentapert (Mcurrentapert-diff);
        else {Setcurrentapert (Mcurrentapert + diff);
        } MPREVX = Event.getx ();
      Mprevy = Event.gety ();
    } break;
    Default:break;
  return true; private void Calculatepoints () {if (mcircleradius-mspace <= 0) {log.e (TAG, "The size of view is too
      Small and spaces is too large ");
    Return
    //mcircleradius-mspace can guarantee the embedded hexagonal in the light circle float Curradius = Mcurrentapert/mmaxapert * (mcircleradius-mspace);
    Using symmetrical relation, reduce computational mpoints[0].x = CURRADIUS/2;
    MPOINTS[0].Y =-curradius * COS_30;
    mpoints[1].x =-mpoints[0].x;
    Mpoints[1].y = MPOINTS[0].Y;
    mpoints[2].x =-curradius;
    MPOINTS[2].Y = 0;
    mpoints[3].x = mpoints[1].x;
    Mpoints[3].y =-MPOINTS[1].Y;
    mpoints[4].x =-mpoints[3].x;
    Mpoints[4].y = MPOINTS[3].Y;
    mpoints[5].x = Curradius;
  MPOINTS[5].Y = 0; //create aperture blades, let art mm provide better private void Createblade () {mblade = Bitmap.createbitmap (MCircleradius, (int) (Mcircleradius * 2 * cos_30), config.argb_8888);
    Path PATH = new Path ();
    Canvas Canvas = new Canvas (Mblade);
    Path.moveto (MSPACE/2/cos_30, mspace);
    Path.lineto (Mblade.getwidth (), Mblade.getheight ());
    Path.lineto (Mblade.getwidth (), mspace);
    Path.close ();
    Canvas.clippath (path);
  Canvas.drawcolor (Mbladecolor); /** * Set the color of the aperture slice * @param bladecolor/public void Setbladecolor (int bladecolor) {Mbladecolor = Bladec
  Olor; /** * Set the aperture background color */public void SetBackgroundColor (int backgroundcolor) {Mbackgroundcolor = BackgroundColor
  ;
  /** * Set the interval between the aperture * @param space/public void setspace (int spaces) {mspace = spaces;
  /** * Set Aperture maximum * @param maxapert */public void Setmaxapert (float maxapert) {mmaxapert = Maxapert; /** * Set Aperture minimum * @param mminapert */public void Setminapert (float mminapert) {This.mminapert = Mminap
  ert } public FLOat Getcurrentapert () {return mcurrentapert; } public void Setcurrentapert (float currentapert) {if (Currentapert > Mmaxapert) {currentapert = Mmaxape
    Rt
    } if (Currentapert < Mminapert) {Currentapert = Mminapert;
    } if (Mcurrentapert = = Currentapert) {return;
    } Mcurrentapert = Currentapert;
    Invalidate ();
    if (maperturechanged!= null) {maperturechanged.onaperturechanged (Currentapert);  }/** * Set aperture value change monitoring * @param listener/public void Setaperturechangedlistener (Aperturechanged listener)
  {maperturechanged = listener;
 }
}

XML for custom attributes:

<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
  <declare-styleable name= "Apertureview" >
    <attr name= "blade_color" format= "color"/> <attr "name=" Background_color "
    Color" format=
    <attr name= "Blade_space" format= "Dimension"/>
  </declare-styleable>
</resources>

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.