O ano novo está chegando e os envelopes vermelhos são infinitos. Quando eu estava pegando envelopes vermelhos, descobri acidentalmente que a interface da bolsa da Lucky do Baidu é muito boa, então dediquei um tempo para escrever um artigo para completar a interface do envelope vermelha do Baidu.
Obviamente, esta é na verdade uma versão evolutiva da interface de desbloqueio. No entanto, ele contém muitos pontos de conhecimento. Escreva uma postagem no blog para gravar e ver quais pontos técnicos específicos estão lá. Confira as renderizações de Baidu:
1. Idéias de programação
Olhando para a interface, não é difícil descobrir que é um recipiente que coloca nove imagens. O desenho pode realmente criar outra visão transparente e é responsável por desenhar linhas e círculos. Em seguida, apresentaremos o processo de implementação.
1. ViewGroup personalizado
Sabemos que o ViewGroup personalizado deve implementar seu método onlayout (). Este método é chamado ao definir a posição e o tamanho da subviagem. Há também um método OnMeasure (), que mede a visão e seu conteúdo para determinar a largura e a altura da vista.
㈡ Corte as posições de seus pontos e círculos e parâmetros de desenho
Ao retornar à interface, o conteúdo da última interface de desenho não será salvo. Deve ser armazenado no caso de redesenhar para desenhar para a interface
㈢ ㈢Simple Zoom Animation
㈣ Custom Visualizar interface de desenho de implementação
㈤ Quando o desenho é concluído, limpe o conteúdo do desenho da interface e verifique se as imagens duplicadas não estão conectadas.
Concluiremos essas etapas abaixo.
2. Personalize o ViewGroup
A tarefa inicial é distribuir uniformemente as nove imagens para a localização das imagens e exibi -las na interface do telefone celular. O código é o seguinte:
Classe public lyjviewGroup estende o ViewGroup implementa LyjestureDrawline.onanimationCallback {/*** Largura de cada área de ponto*/Private Int ChildWidth;/**** Contexto*/contexto privado;/**** Localização do ponto de imagem*/Lista privada <lyJesturepoint> */private lyjgestureview geardrawline; private int basenum = 5; public lyjviewGroup (contexto de contexto) {super (context); this.Context = context; this.List = new ArrayList <> ();) METRICATRICSTRIC = new DisplayMetrics ((Atividade)). = metric.widthpixels / 3; // largura da tela (pixels) addChild (); // inicialize um visualizador de linha que pode desenhar linhas = new lyjgestureview (contexto, list); gesturedrawline.setanimationCallback (this);} public void setParentView (ViewGroup Parent) {// Obtenha o widthing da tela Metrics Metrics Metrics = context) .getWindowManager (). getDefaultDisplay (). getMetrics (métrico); int width = metric.widthpixels; layoutparams layoutparams = new layoutParams (largura, largura); this.setLayoutParams (layoutParams); gestredrawline.setLayoutParams (layoutParams); parent.addview (this); parent.addview (gestredrawline); i++) {//What row int rowspan = i / 3;//What column int column = i % 3;android.view.View v = getChildAt(i);v.layout(column * childWidth + childWidth / baseNum, rowspan * childWidth + childWidth / baseNum,column * childWidth + childWidth - childWidth / Basenum);}}@Substitua prototecida vazio onMeasure (int widthMeasurespec, int a altitudeMeasuresPec) {super.onMeasure (WidthMeasurespec, HeightMeasurespec); // Traversal Defina o tamanho de cada visualização infantil para (int = 0; i <getchildCount (i+); getChildat (i); v.Measure (widthMeasurespec, altionmeasurespec);}} private void addChild () {for (int i = 0; i <9; i ++) {imageview = new ImageView (context); image.setBackResource (r.drawable.marker); thisDeview (imagem); 3;// Which column int column = i % 3;// Define the coordinates of the upper left and lower right corners of the point int leftX = column * childWidth + childWidth / baseNum;int topY = rowspan * childWidth + childWidth / baseNum;int rightX = column * childWidth + childWidth - childWidth / baseNum;int bottomY = rowspan * largura infantil + largura infantil - largura de criança / basenum; lyjgesturepoint p = novo lyjgesturepoint (leftx, topy, rightx, lotado, i); this.list.add (P);}}@substituição de@substituir o anulação startAnimationImage (int i) {animação de animação = animação. R.anim.gridlayout_child_scale_anim); getChildat (i) .startanimation (animação);}}3. Personalize as classes de ponto
Como o nome sugere, é obter os atributos relevantes do ponto, entre os quais as coordenadas do canto superior esquerdo da imagem básica do atributo e as coordenadas do canto inferior direito da figura, calcule a posição central da figura para obter o ponto central da figura. Marca de status indicando se o ponto é atraído para a figura. Aqui estão as classes físicas:
public class LyjgesturePoint {private ponto Pointlefttop; // Coordenar o canto esquerdo superior Pointrightbottom; // Coordenada do canto direito inferior private int Centerx; // ponto de imagem x coordenada private Int Centery Int; pointState;}public void setPointState(int pointState) {this.pointState = pointState;}public Point getPointLeftTop() {return pointLeftTop;}public Point getPointRightBottom() {return pointRightBottom;}public LYJGesturePoint(int left,int top,int right,int bottom,int i){this.pointLeftTop=new Ponto (esquerda, superior); this.poIntrightBottom = new Point (direita, inferior); this.num = i;} public int getCentex () {this.centerx = (this.pointleftTop.x+this.PoiTrightBottom.x)/2; Return Centerx;} public int getCentery () {this.centery = (this.pointlefttop.y+this.poiTrightbottom.y)/2; Centery de retorno;}}4. Classe de círculo personalizado
Esta classe é mais simples e possui três propriedades (coordenadas e raio do ponto central do círculo). O código é o seguinte:
public class lyjcirclepoint {private int redondx; // ponto central do círculo x coordenar privado int redondy; // ponto central de círculo y coordenada private int radiu; // círculo raio public int getRadiu () {return radiU;} public int getroundx () {redondx; radiu) {this.Roundx = redondx; this.Roundy = redondy; this.radiu = radiu;}}5. Implementar a vista de classe de desenho personalizado
O código é o seguinte:
Public Class LyjgestureView estende Android.View.View {/**** Declare o pincel de linha reta*/tinta privada;/**** Declare a escova de círculo*/Paint de tinta privada;/**** tela*/tela privada é que a coleta de cada coleção; Lista <lyjgesturepoint> list;/**** Registre as linhas desenhadas*/Lista privada <par <lyjgesturepoint, lyjgesturepoint >> linelist;/**** Registre o círculo desenhado*/Private List <lyjcirclepointpointpointpointspoint); AnimationCallback; interface pública onanimationCallback {public void startanimationImage (int i);} public void setAnimationCallback (onanimationCallback AnimationCallback) {this.animationCallback = animationCallback;} public lyjgestureView (contexto, list <lyjgestpoint) list) {super (context); log.i (getClass (). getName (), "gestredrawline"); pintura = new pint (pinting.dither_flag); // crie um pincel circlepaint = nova tinta (pintur.dither_flag); displaymetrics métrica = novo DisplayMetrics (); (((atividade) contexto) .getWindowManager (). GetDefaultDisplay (). GetMetrics (métrico); log.i (getClass (). GetName (), "widthPixels" + metric.widthpixels); log.i (getClass (). Bitmap.createbitmap (metric.widthpixels, metric.heightpixels, bitmap.config.argb_8888); // Defina a largura e a altura da tela de bitmap = new Canvas (); canvas.setBitmap (bitmap); pintur.setStyle (pintur.style.stroke); // Definir tinta não-atrevida.SetSTrokeWidth (20); // largura de Pen 20 pixels.setColor (cor.rgb (20); Paint.Setantialias (true); // não exibiu CirccledPaint.SetStyle (Paint.style.fill); Circlepaint.SetSTrokeWidth (1); CirclePaint.Setantialias (True); Circlepaint.SetColor (color.rgb (245, 142, 33); ArrayList <> (); this.circlePoints = new ArrayList <> ();}@substituir o público booleano OnTouchEvent (Evento MotionEvent) {switch (Event.getAction ()) {Case Motion.Action_Down: // Determina o ponto do clique está em current = (getpointat (int). null) {currentPoint.SetPointState (constantes.point_state_selected); this.animationCallback.StarTanimationImage (currentPoint.getNum ()); canvas.drawcircle (currentpoint.getCenterx (), currentpoint.getCentery (), 20, circlepaint); circingpoint.add (newjcircleint (currentCoint); MotionEvent.Action_Move: ClearScreenAnddrawlist (); // Obtenha o ponto em que a posição de movimento atual é LyjgesturePoint Pointat = getPointat ((int) event.getx (), (int) event.gety ()); if (currentpoint == null && Pointat == null) {// Pressione seu dedo para o toque para o slide. Se o ponto final e o ponto de partida não forem a imagem, retorne true;} else {// significa que o dedo do usuário é movido para o ponto se (currentpoint == null) {// primeiro determina se o ponto atual é nulo // se estiver vazio, atribua o ponto que você mudou para o currentCurrentpoint = Pointat; // Definir o ponto de corrente para selecionar; currentpoint.setPointState (constants.point_state_selected);}} // Se o ponto em que você se moveu não for a área da imagem ou se mova para o seu próprio lugar, ou a imagem já estiver selecionada, basta desenhar uma linha reta se (Pointat == NULL || Currentpoint.Equals (Pointat) || Constants.Point_state_selected == PointAt.getPointState ()) {Canvas.DrawCircle (currentPoint.getCenterx (), currentpoint.getCentery (), 20, Circlepaint); Circleint.add (new LyjcirclePoint (CurrentPoint.getCenterx (), currentPoint.getCentery (), 20); CanVAs.Dawline.Dawline (CurrentPointx (), CurrentPoint.getCentery (), 20); CanVAs.Dawline.Drawline (CurrentPointx (), CurrentPoint.getCentery, 20); event.getx (), event.gety (), tinta);} else {// desenhe duas linhas retas em outras situações, salve o círculo de desenho e a linha reta e chame a animação de zoom da imagem pressionada tela.drawcircle (pointat.getCentex (), Pointat.GetCenty (), 20, circpaiNCoToints.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ds.ad (), círculo (círculo) (PointAtToint.getCenterx (), PointTerCenty (), 20, círculo); pointAt.getCenterY(), 20));this.animationCallback.startAnimationImage(pointAt.getNum());pointAt.setPointState(Constants.POINT_STATE_SELECTED);canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), pointAt.getCenterX(), pointAt.getCenterY(), paint);Pair<LYJGesturePoint, Lyjgesturepoint> par = novo par <> (currentpoint, Pointat); lineList.add (par); currentpoint = Pointat; // Defina o ponto selecionado para o ponto atual. } invalidate (); // repete; case motionEvent.action_up: clearscreenandDrawlist (); // impedir uma linha extra sem ponto final new Handler (). void run () {// Limpe a coleção de pontos de salvamento e círculos lineList.clear (); circingpoints.clear (); // re-draw the interface clearscreenandDrawlist (); para (lyjgesturepoint P: list) {// Defina -o para inicializar o estado não selecionado P.SetPointState (constants.Point_State_Normal);} invalidate ();}}/*** através da posição de ponto, vá para a coleção para encontrar o ponto que este ponto é incluído em ** @param x* @param y* @Return Pontos*/private lyjgesturepoint getPointat (int x, int y) {for (lyjgesturepoint Point: list) {// primeiro determina se o ponto está na coordenada x da imagem int leftx = Point.getpointlefttop (). Próxima comparação continua;} // No julgamento, se o ponto está na coordenada y da imagem int topy = Point.getPointLeftTop (). Y; int Bottomy = Point.getPoIntRightBottom (). Y; se o que é (y> atravessando até o ponto. Ponto de retorno;} retornar nulo;}/*** Limpe todas as linhas na tela e, em seguida, desenhe as linhas na coleção*/private void clearscreenandDrawlist () {Canvas.drawcolor (color.transparent, PorterDuff.mode.clear); Para (par <lyjgesturepoint, lyjgesturepoint> par: lineList) {Canvas.drawline (par.first.getCenterx (), par.first.getCentery (), par.second.getCentex (), par.SeCondCentery (), pintura); circpoints) {Canvas.drawcircle (lyjcirclepoint.getRoundx (), lyjcirclepoint.getRoundy (), lyjcirclepoint.getRadiu (), circcingpaint);}} // desenhar o canvas criado com bitmap @overrideProttected onrwraw (latavas); {Canvas.drawbitmap (bitmap, 0, 0, null);}}Dessa forma, você pode obter o seguinte efeito de interface (é claro, descompilar a carteira Baidu, não há imagem na carteira Baidu, então você precisa encontrar uma imagem aleatória):