La nouvelle année arrive et les enveloppes rouges sont infinies. Lorsque je saisissais des enveloppes rouges, j'ai découvert accidentellement que l'interface de sac de sac de Baidu est assez bonne, j'ai donc pris le temps d'écrire un article pour compléter l'interface d'enveloppe rouge de Baidu.
Bien sûr, il s'agit en fait d'une version évolutive de l'interface de déverrouillage. Cependant, il contient pas mal de points de connaissance. Écrivez un article de blog pour l'enregistrer et voyez quels points techniques spécifiques existent. Découvrez les rendus de Baidu:
1. Idées de programmation
En regardant l'interface, il n'est pas difficile de constater qu'il s'agit d'un conteneur qui met neuf images. Le dessin peut en fait créer une autre vue transparente et est responsable du dessin de lignes et de cercles. Ensuite, nous présenterons le processus de mise en œuvre.
1. ViewGroup personnalisé
Nous savons que Custom ViewGroup doit implémenter sa méthode OnLayout (). Cette méthode est appelée lors de la définition de la position et de la taille de la sous-vue. Il existe également une méthode OnMeasure (), qui mesure la vue et son contenu pour déterminer la largeur et la hauteur de la vue.
㈡Storing les positions de ses points et cercles et paramètres de dessin
Lors du retour à l'interface, le contenu de la dernière interface de dessin ne sera pas enregistré. Il doit être stocké en cas de redessinage pour dessiner à l'interface
㈢ animation de zoom simple
Interface de dessin de l'implémentation de vue de la vue.
㈤Lorsque le dessin est terminé, effacez le contenu de dessin d'interface et assurez-vous que les images en double ne sont pas connectées.
Nous terminerons ces étapes ci-dessous.
2. Personnaliser ViewGroup
La tâche initiale consiste à distribuer uniformément les neuf images à l'emplacement des images et à les afficher dans l'interface du téléphone mobile. Le code est le suivant:
classe publique LyjViewGroup étend ViewGroup implémente lyjgeredrawline.onanimationCallback {/ *** Largeur de chaque zone de point * / private int childwidth; / **** context * / private context context; / **** emplacement du point de vue * / Liste privée <lyjgestRepoint> Liste; / **** Créer une vue pour être au-dessus du groupe de vue. * / private lyjgestureView GearDrawline; private int basenum = 5; public lyjViewGroup (contexte context) {super (context); this.context = context; this.list = new ArrayList <> (); displayMetrics Metric = new DisplayMetdisplay (((Activity) context) .getWindowManager (). GetDefaultDisplay (). GetMetrics (Metric); Metric.WidthPixels / 3; // La largeur d'écran (Pixels) addChild (); // initialise une vue de vue qui peut dessiner des lignes = new LyjgetureView (context, list); gestureDrawline.SetAnimationCallback (this);} public void setParentView (ViewGroup Parent) {// Obtenez la largeur de l'écran MetricMetrrics Metric = New DisplayMetricS (); (activité); (activité) Context) .getWindowManager (). GetDefaultDisplay (). GetMetrics (Metric); int width = Metric.WidthPixels; LayoutParams LayoutParams = new LayoutParams (Width, Width); this.setLayoutParams (LayoutParams); gesturedrawline.SetLayoutParams (LayoutParams); parent.AddView (this); parent.adddView (gesturedRawline);} @ OverRideProtected Void Onlayout (Boolean Changed, int l, int t, int r, int b) {pour (int i = 0; i <GetchCild ();); i ++) {// quelle row int wowspan = i / 3; // quelle colonne int column = i% 3; android.view.view v = getchildat (i); v.layout (colonne * childwidth + childwidth / basenum, wowspan * childwidth + childwidth / basenum, colonne * childwidth + childwidTh -ffredwidth / basenum, colonne * childwidth + childwidTh-ChildWidth / Basenum);}} @ OverRideProtected void OnMeasure (int widthMeasurespec, int heightmeasurespec) {super.onmeasure (widthmeasurespec, heightmeasurespec); // set la taille de chaque vue d'enfant pour (int i = 0; i <getChildCount (); i ++) {View v = getChildat (i); v.Measure (widthmeasurespec, heightmeasurespec);}} private void addchild () {for (int i = 0; i <9; i ++) {imageView image = new ImageView (context); image.setbackgroundResource (r.Drrawable.marker); this.addview (image); invalid 3; // quelle colonne int colonne = i% 3; // définissez les coordonnées de la haute gauche et des coins inférieurs à droite du point int LeftX = colonne * ChildWidth + ChildWidth / Basenum; int RightX = Colonne * Infiltwidth-Basenth / Basenum; ChildWidth + ChildWidth - ChildWidth / Basenum; LyjgesturePoint p = new LyjgesturePoint (LeftX, Topy, RightX, Bottomy, i); this.list.add (p);}} @ Overdepublic Void startanimationImage (int i) {Animation Animation = AnimationUtils.loadanimation (GetContex R.anim.gridlayout_child_scale_anim); getchildat (i) .startanimation (animation);}}3. Personnaliser les classes de points
Comme le nom l'indique, il s'agit d'obtenir les attributs pertinents du point, parmi lesquels les coordonnées du coin supérieur gauche de l'image de base de l'attribut et les coordonnées du coin inférieur droit de l'image, calculent la position centrale de l'image pour obtenir le point central de l'image. Marque d'état indiquant si le point est tracé sur l'image. Voici les classes physiques:
classe publique LyjgesturePoint {private Point PointLeftTOP; // COORDINATION PRIVATE PRIVÉ PRIVATE PORTING POINTRIGHTBOTTO PointState;} public void setpointState (int pointstate) {this.pointstate = pointstate;} public point getPointLeftTop () {return PointLeftTop;} public GetPoinTrightBottom () {return pointrightbottom;} public lyjgettePoint (int Left, int top, int, int i) {this.pointlef Point (gauche, haut); this.poinTrightBottom = new Point (droite, en bas); this.num = i;} public int getCenterx () {this.centerx = (this.pointlefttop.x + this.poinTrightBottom.x) / 2; return CenterX;} public int getCentery () {this.centery = (this.pointleftop.y + this.poinTrightBottom.y) / 2; Retour Centery;}}4. Classe de cercle personnalisé
Cette classe est plus simple et a trois propriétés (coordonnées et rayon du point central du cercle). Le code est le suivant:
public class LYJCirclePoint {private int roundX;//Circle center point X coordinate private int roundY;//Circle center point Y coordinate private int radiu;//Circle radius public int getRadiu() {return radiu;}public int getRoundX() {return roundX;}public int getRoundY() {return roundY;}public LYJCirclePoint(int roundX,int roundY,int radiu) {this.roundx = rondx; this.roundy = rond; this.radiu = radiu;}}5. Implémentez la vue de la classe de dessin personnalisée
Le code est le suivant:
classe publique LyjgesttureView étend Android.View.view {/ **** Déclarer le pinceau en ligne droite * / peinture de peinture privée; / **** Declare Circle Brush * / Private Paint Circlepaint * / **** Canvas * / Private Canvas Canvas; / **** bitmap * / privé bitmap bitmap; / **** Une collection de coordonnées de vue> est utilisée pour déterminer si les points sont dans l'informatique * une collection de coordonnées de vue> Liste; / **** Enregistrer les lignes dessinées * / Liste privée <Pair <LyjgestRepoint, Lyjgesturepoint >> Linelist; / **** Enregistrer le cercle dessiné * / Liste privée <LyjCirclePoint> CirclePpoint; / *** Quel point est le doigt actuellement dans * / privé LyjgestRepointpoint; / **** Appuyez sur l'animation * / Publication AnimerCall AnimationCallCall; void startAnimationImage (int i);} public void setanimationCallback (onanimationCallback AnimationCallback) {this.animationCallback = AnimationCallback;} public lyjgetteView (context, list <lyjgettepoint> liste) {super (context); Log.i (getClass (). GetName (), "GesteredRaw"); Paint = Paint = GetName (), "Gesteredraw"); Peinture (peinture.dither_flag); // Créer un pinceau CirclePaint = new Paint (peinture.Dther_flag); DisplayMetrics Metric = new DisplayMetrics (); ((Activity) Context) .GetWindowManager (). GetDefaultDisplay (). GetMetrics (Metric); Log.i (getClass (). GetName (), "WidthPixels" + Metric.WidthPixels); log.i (getClass (). GetName (), "HeightPixels" + Metric.HeightPixels); bitmap = bitmap.create Bitmap.config.Argb_8888); // définir la largeur et la hauteur du bitmap canvas = new canvas (); canvas.setbitmap (bitmap); peinture.setsstyle (peinture.style.stroke); // définir la peinture non-fill.setstrokewidth (20); // la large largeur 20 pixels peinture.setcolor (colori.rgb (245, 142, 33)); peinture.setantialias (true); // non affiché CirclePaint.SetStyle (peinture.style.fill); CirclePaint.SetStrokeWidth (1); CirclePaint.Setantialias (True); CirclePaint.SetColor (Color.rgb (245, 142, 33)); this.list = list; this.lineLelist = new ArrayList <> (); this.Circlepoints = new ArrayList <> ();} @ OverRidepublic Boolean Ontouchevent (MotionEvent Event) {Switch (event.getAction ()) {Case MotionEventid.Action_Down: // Détermine quel point le clic actuel est dans CurrentPoint = GetPointAt ((int) event.getx (), (int) event.gety ()); {currentPoint.setPointState (constants.point_state_selected); this.animationCallback.StartAnimationImage (CurrentPoint.getNum ()); Canvas.DrawCircle (CurrentPoint.getCenterx (), CurrentPoint.getCentery (), 20, CirclePaint); Circlepoint.Add (New LyjCirclePoint (CurrentPoint.getCenterx (); Casepoint.getCentery (), 20));} Invalidate (); MotionEvent.Action_Move: ClearScreenandDrawList (); // Obtenez le point où la position mobile actuelle est LyjgestRepoint Pointat = GetPointAt ((int) event.getX (), (int) event.gety ()); if (currentPoint == null && pointat == null) {// Appuyez sur votre doigt sur l'écran pour le glisser. Si le point final et le point de départ ne sont pas l'image, renvoyez true;} else {// Cela signifie que le doigt de l'utilisateur est déplacé vers le point si (currentPoint == null) {// Déterminez d'abord si le point actuel est nul // s'il est vide, alors attribuez le point à vous déplacer vers CurrentPointCurrentPoint = Pointat; // Définissez le point de courant pour sélectionner l'état; currentPoint.setPointState (constants.point_state_selected);}} // Si le point où vous avez déménagé n'est pas la zone d'image ou se déplacer à votre propre endroit, ou si l'image est déjà sélectionnée, tracez simplement une ligne droite si (pointat == null || currentPoint.equals (Pointat) || constants.point_state_selected == PointAt.getPointState ()) {Canvas.DrawCircle (CurrentPoint.getCenterX (), CurrentPoint.getCentery (), 20, CirclePaint); CirclePoint.Add (New Lyjcirclepoint (CurrentPoint.getCenterx () event.getx (), event.gety (), peinture);} else {// dessiner deux lignes droites dans d'autres situations, enregistrer le cercle de dessin et la ligne droite, et appelez l'animation zoom de l'image pressée canvas.drawcircle (Pointat.getCenterx (), pointat.getCentery (), 20, CirclePaint); Circlepoint.Addd (new LyjCirclepoint (PointAt.GentRex (); Pointat.getCentery (), 20)); this.animationCallback.startAnimationImage (Pointat.getNum ()); PointAt.SetPointState (constants.point_state_selected); canvas.drawline (actuel Lyjgesturepoint> paire = new pair <> (currentpoint, pointat); linelist.add (paire); currentPoint = pointat; // définissez le point sélectionné sur le point actuel. } invalidated (); // repeindre la rupture; case motionEvent.action_up: clearscreenandDrawList (); // empêcher une ligne supplémentaire sans point final new a manager (). void run () {// effacer la collection de points de sauvegarde et de cercles lineList.Clear (); cerclepoints.clear (); // ré-repliez l'interface clearscreenandDrawlist (); pour (LyjgesturePoint p: list) {// Définissez-le pour initialiser l'état non sélectionné P.SetPointState (constants.point_state_normal);} invalidate ();}} / *** via la position de point, accédez à la collection pour trouver le point ce point est inclus dans ** @param x * @param y * @return si non trouvé, retour nul Points * / private lyjgettepoint getPointAt (int x, int y) {for (lyjgesturepoint point: list) {// déterminez d'abord si le point est dans la coordonnée x de l'image int LeftX = Point.getPointLeftop (). Comparaison continue;} // dans le jugement si le point se trouve dans la coordonnée y de l'image int topy = point.getPointLeftOp (). y; int bottomy = point.getPoinTrightBottom (). au point. Retour Point;} return null;} / *** effacer toutes les lignes de l'écran, puis tracer les lignes dans la collection * / private void clearscreenandDrawlist () {canvas.drawColor (colore.transparent, porterduff.mode.clar); for (pair <lyjgesturepoint, lyjgesturepoint> paire: linelist) {canvas.drawline (pair.first.getCenterx (), pair.first.getCentery (), pair.second.getCenterx (), pair.second.getCentery (), peinture); // draw line} for (lyjcirclepointpoint circlePoints){canvas.drawCircle(lyjCirclePoint.getRoundX(), lyjCirclePoint.getRoundY(), lyjCirclePoint.getRadiu(), circlePaint);}}// Draw the canvas created with bitmap @Overrideprotected void onDraw(Canvas canvas) {canvas.drawBitmap(bitmap, 0, 0, null);}}De cette façon, vous pouvez obtenir l'effet d'interface suivant (bien sûr, décompilant le portefeuille Baidu, il n'y a pas d'image dans le portefeuille Baidu, vous devez donc trouver une image aléatoire):