Android自定义控件实现支付宝记账饼图

本文实例为大家分享了Android实现支付宝记账饼图,点击旋转到最下面,供大家参考,具体内容如下

代码:

package com.example.a_102.myapplication7.ui; 

import java.util.ArrayList;
import java.util.List; 

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator; 

import com.example.a_102.myapplication7.util.Util; 

/**
 *
 */
public class SelectPieView extends View { 

 private static final String TAG = "CustomPie_tag";
 private int width;
 private SelectPieCallBack mCallBack;
 private boolean initPostion = false;
 /**
  * 当前选中的区域
  */
 private int currentDownPostion; 

 public SelectPieView(Context context) {
  super(context);
 } 

 public SelectPieView(Context context, AttributeSet attrs) {
  super(context, attrs);
 } 

 public SelectPieView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 } 

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  int width;
  int hight; 

  int widthmode = MeasureSpec.getMode(widthMeasureSpec);
  int widthsize = MeasureSpec.getSize(widthMeasureSpec); 

  int hightmode = MeasureSpec.getMode(heightMeasureSpec);
  int hightsize = MeasureSpec.getSize(heightMeasureSpec); 

  if (MeasureSpec.EXACTLY == widthmode) {
   width = widthsize;
  } else {
   width = 200;
   if (MeasureSpec.AT_MOST == widthmode) {
    width = Math.min(widthsize, 200);
   }
  } 

  if (MeasureSpec.EXACTLY == hightmode) {
   hight = hightsize;
  } else {
   hight = 200;
   if (MeasureSpec.AT_MOST == hightmode) {
    hight = Math.min(hightsize, 200);
   }
  } 

  setMeasuredDimension(Math.min(width, hight), Math.min(width, hight));
 } 

 /**
  * 笔宽
  */
 private int mPaintWid;
 /**
  * 外边圆半径
  */
 private int mOutRoot;
 /**
  * 内边圆半径
  */
 private int mIntRoot;
 /**
  * 空白处宽度
  */
 private int emptysize = -1;
 /**
  * 点击前的圆和点击后的圆半径差距
  */
 private float betweenSize = 10;
 /**
  * 向限
  */
 private int XIANGXAIN;
 /**
  * 开始的角度
  */
 private float start = 360;
 /**
  * 旋转过的角度
  */
 private List<startAndRoatData> haveRoats = new ArrayList<>();
 /**
  *
  */
 private String mTitle = "总消费";
 /**
  *
  */
 private String mSubTitle = "00";
 /**
  *
  */
 private String mSubTitleDot = "00";
 /**
  * 是否在运行
  */
 private boolean isRun = true; 

 private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 

 private Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 /**
  * 整数部分
  */
 private Paint textPaintSubTitle= new Paint(Paint.ANTI_ALIAS_FLAG);
 /**
  * 小数部分
  */
 private Paint textPaintSubTitleDot= new Paint(Paint.ANTI_ALIAS_FLAG); 

 @Override
 protected void onDraw(Canvas canvas) {
  // reSetData();
  if (null == datas || datas.size() == 0)
   return;
  width = getWidth();
  mOutRoot = width / 2;
  mPaintWid = Util.dip2px(getContext(), 40);
  mIntRoot = mOutRoot - mPaintWid; 

  paint.setStyle(Paint.Style.STROKE);
  paint.setColor(Color.RED);
  paint.setStrokeWidth(mPaintWid);
  RectF rt = new RectF(mPaintWid / 2 + betweenSize, mPaintWid / 2 + betweenSize,
    width - mPaintWid / 2 - betweenSize, width - mPaintWid / 2 - betweenSize);
  RectF rt2 = new RectF(mPaintWid / 2, mPaintWid / 2, width - mPaintWid / 2, width - mPaintWid / 2); 

  int size = datas.size();
  float allValues = 0;
  for (int i = 0; i < datas.size(); i++) {
   allValues += datas.get(i).getValuse();
  }
  // allValues = allValues + emptysize * size;
  float sigleSize = (360 - emptysize * datas.size()) / (allValues * 1f); 

  float end = 0;
  haveRoats.clear();
  for (int i = 0; i < size; i++) {
   paint.setColor(getResources().getColor(datas.get(i).getColor()));
   end = datas.get(i).getValuse() * sigleSize; 

   if (!isRun && datas.get(i).getPostion() == currentDownPostion && datas.size()>1) {
    canvas.drawArc(rt2, start + 3, end - 6, false, paint);
    canvas.drawArc(rt, start + 3, end - 6, false, paint);
   } else {
    canvas.drawArc(rt, start, end, false, paint);
   }
   Log.i(TAG, "first=" + start % 360 + "==" + end + "postion=" + datas.get(i).getPostion()); 

   haveRoats.add(new startAndRoatData(datas.get(i).getPostion(), start % 360, end)); 

   start = start + end + emptysize; 

  } 

  textPaint.setStrokeWidth(Util.dip2px(getContext(), 1));
  /** 画图片 */
  for (int i = 0; i < haveRoats.size(); i++) {
   startAndRoatData startAndRoatData = haveRoats.get(i); 

   float x = 0;
   float y = 0; 

   if (!isRun && currentDownPostion == haveRoats.get(i).getPostion() && datas.size()>1) { 

    x = (float) (Math
      .cos(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))
      * (mIntRoot + mPaintWid / 2) + mOutRoot);
    y = (float) (Math
      .sin(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))
      * (mIntRoot + mPaintWid / 2) + mOutRoot);
   } else {
    x = (float) (Math
      .cos(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))
      * (mIntRoot + mPaintWid / 2 - betweenSize) + mOutRoot);
    y = (float) (Math
      .sin(Math.PI / 180 * (startAndRoatData.getStartAng() + startAndRoatData.getRoatAng() / 2))
      * (mIntRoot + mPaintWid / 2 - betweenSize) + mOutRoot);
   } 

   Rect rect = new Rect((int) (x - mPaintWid / 3), (int) (y - mPaintWid / 3), (int) (x + mPaintWid / 3),
     (int) (y + mPaintWid / 3)); 

   int width = BitmapFactory.decodeResource(getResources(), datas.get(i).getIcon()).getWidth();
   // L=n(圆心角度数)× π(圆周率)× r(半径)/180(角度制)
   if (startAndRoatData.getRoatAng() * Math.PI * (mIntRoot + mPaintWid / 2) / 180 > width) {
    canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), datas.get(i).getIcon()), null, rect,
      null);
   }
  } 

  textPaint.setStyle(Paint.Style.FILL);
  textPaint.setTextSize(Util.dip2px(getContext(), 14));
  /** 写文字 */
  canvas.drawText(mTitle, width / 2 - (textPaint.measureText(mTitle)) / 2,
    width / 2 - Util.dip2px(getContext(), 8), textPaint); 

  textPaintSubTitle.setTextSize(Util.dip2px(getContext(), 20));
  canvas.drawText(mSubTitle,
    width / 2 - (textPaintSubTitle.measureText(mSubTitle)) / 2 - (textPaintSubTitleDot.measureText("."+mSubTitleDot) / 2),
    width / 2 + Util.dip2px(getContext(), 15), textPaintSubTitle); 

  textPaintSubTitleDot.setTextSize(Util.dip2px(getContext(), 15));
  canvas.drawText("." + mSubTitleDot,
    width / 2 + textPaintSubTitle.measureText(mSubTitle) /2 - (textPaintSubTitleDot.measureText("." + mSubTitleDot))/2,
    width / 2 + Util.dip2px(getContext(), 15), textPaintSubTitleDot);
  //Toast.makeText(getContext(), "=="+textPaint.measureText(mSubTitle), Toast.LENGTH_SHORT).show();
  /** 测试基线 */
  /*
   * paint.setColor(Color.BLACK);
   * paint.setStrokeWidth(Util.dip2px(getContext(), 1));
   *
   * canvas.drawLine(0, width / 2, width, width / 2, paint);
   * canvas.drawLine(width / 2, 0, width / 2, width, paint);
   */
  /**
   * 初始化位置
   * */
  if (!initPostion) {
   initPostion = true; 

   startAndRoatData roatData = haveRoats.get(0);
   float currentCenterAng = roatData.getStartAng() + roatData.getRoatAng() / 2;
   if (currentCenterAng < 90) {
    starRoat(start, start + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), false);
   } else if (currentCenterAng > 90 && currentCenterAng < 270) {
    starRoat(start, start - (currentCenterAng - 90), false);
   } else {
    starRoat(start, start + 360 + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), false);
   }
   currentDownPostion = roatData.getPostion();
   isRun = false;
   invalidate();
  } 

 } 

 /**
  * 设置显示金额
  *
  * @param number
  */
 public void setNumber(String number) {
  if (TextUtils.isEmpty(number)) {
   number = "0.00";
  }
  if (number.contains(".")) {
   String[] split = number.split("\\.");
   mSubTitle = split[0];
   mSubTitleDot = split[1];
  } else {
   mSubTitle = number;
   mSubTitleDot = "00";
  }
  if (mSubTitleDot.length() > 2) {
   mSubTitleDot = mSubTitleDot.substring(0, 2);
  }
 } 

 private int Lxy2; 

 @Override
 public boolean onTouchEvent(MotionEvent event) { 

  switch (event.getAction()) {
  case MotionEvent.ACTION_DOWN:
   float x = event.getX();
   float y = event.getY();
   double atan = Math.atan((x - mOutRoot) / (mOutRoot - y));
   double currntAngle = (atan / Math.PI * 180);
   double clickAngle = 0;
   Lxy2 = (int) Math.pow(x - mOutRoot, 2) + (int) Math.pow(mOutRoot - y, 2);
   if (Math.pow(mIntRoot, 2) < Lxy2 && Lxy2 < Math.pow(mOutRoot, 2)) { 

    if (x > width / 2 && y > width / 2) {
     /** currntAngle第四象限是负数 */
     // starRoat(start, (float) (start - currntAngle), true);
     clickAngle = currntAngle +90; 

    } else if (x > width / 2 && y < width / 2) {
     /** currntAngle第一象限是负数 */
     //starRoat(start, (float) (start + 180 - currntAngle), true);
     clickAngle = currntAngle +270;
    } else if (x < width / 2 && y < width / 2) {
     /** currntAngle第二象限是正数 */
     //starRoat(start, (float) (start - (180 - Math.abs(currntAngle))), true);
     clickAngle = currntAngle +270;
    } else {
     /** currntAngle第三象限是正数 */
     //starRoat(start, (float) (start - Math.abs(currntAngle)), true);
     clickAngle = currntAngle +90;
    } 

    int i = clickDownPostion(clickAngle);
    startAndRoatData roatData = haveRoats.get(i);
    currentDownPostion = roatData.getPostion();
    float currentCenterAng = roatData.getStartAng() + roatData.getRoatAng() / 2;
    if (currentCenterAng < 90) {
     starRoat(start, start + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), true);
    } else if (currentCenterAng > 90 && currentCenterAng < 270) {
     starRoat(start, start - (currentCenterAng - 90), true);
    } else {
     starRoat(start, start + 360 + 90 - (roatData.getStartAng() + roatData.getRoatAng() / 2), true);
    } 

   } 

   return true;
  } 

  return super.onTouchEvent(event);
 } 

 private int clickDownPostion(double clickAngle) {
  for (int i = 0; i < haveRoats.size(); i++) {
   startAndRoatData data = haveRoats.get(i);
   if ((data.getStartAng() < clickAngle && data.getStartAng() + data.getRoatAng() > clickAngle)
     || (data.getStartAng() + data.getRoatAng() > 360
       && ((data.getStartAng() + data.getRoatAng()) % 360) > clickAngle)) {
    return i;
   }
  }
  return 0;
 } 

 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 public void starRoat(final float star, final float end, boolean isSmooth) {
  ValueAnimator valueAnimator = ValueAnimator.ofFloat(star, end);
  valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator animation) {
    float animatedValue = (float) animation.getAnimatedValue();
    start = animatedValue;
    isRun = true;
    invalidate();
   }
  });
  valueAnimator.setDuration(isSmooth ? (long) (700) : 10);
  valueAnimator.setInterpolator(new AccelerateInterpolator());
  valueAnimator.start();
  valueAnimator.addListener(new Animator.AnimatorListener() {
   @Override
   public void onAnimationStart(Animator animation) { 

   } 

   @Override
   public void onAnimationEnd(Animator animation) { 

    if (currentDownPostion == -1) {
     start++;
     starRoat(start, start++, false);
    } else {
     isRun = false;
     invalidate();//画突出部分
     mCallBack.currentPostion(currentDownPostion);
    }
   } 

   @Override
   public void onAnimationCancel(Animator animation) { 

   } 

   @Override
   public void onAnimationRepeat(Animator animation) { 

   }
  });
 } 

 private List<PieData> datas = new ArrayList<>(); 

 public void reSetData(List<PieData> data) {
  datas.clear();
  datas.addAll(data);
  float all =0;
  for (PieData da : datas) {
   all += da.getValuse();
  }
  if (all < 360) {
   for (PieData da : datas) {
    da.setValuse(da.getValuse() * 200);
   }
  }
  for (PieData da : datas) {
   all += da.getValuse();
  }
  /**强制设置最低值*/
  for (PieData da : datas) {
   if (da.getValuse() / all < 0.03) {
    da.setValuse((float) (all * 0.03));
   }
  } 

  invalidate(); 

 } 

 /**
  * 判断当前选择的所在区间
  *
  * @return
  */
 private int findCurrentDownPostion() {
  if (haveRoats == null || haveRoats.size() <= 0) {
   return 1;
  } 

  for (int i = 0; i < haveRoats.size(); i++) { 

   float startAng = haveRoats.get(i).getStartAng();
   float roatAng = haveRoats.get(i).getRoatAng();
   //Utility.Logi(TAG, "currentpostion=sstar=" + startAng + "===rroat=" + roatAng);
   if (startAng < 90 && (startAng <= 90 && startAng + roatAng > 90)) {
    // Utility.Logi(TAG, "currentpostion=" + haveRoats.get(i).getPostion());
    return haveRoats.get(i).getPostion();
   } else if (startAng > 90 && startAng - 360 + roatAng > 90) {
    //Utility.Logi(TAG, "currentpostion=" + haveRoats.get(i).getPostion());
    return haveRoats.get(i).getPostion();
   }
  }
  return -1;
 } 

 public void setCallBack(SelectPieCallBack callBack) {
  this.mCallBack = callBack;
 } 

 public interface SelectPieCallBack {
  void currentPostion(int postion);
 } 

 public static class PieData { 

  public PieData(int postion, float valuse, int color, int icon) {
   this.postion = postion;
   this.valuse = valuse;
   this.color = color;
   this.icon = icon;
  } 

  private int postion; 

  private float valuse; 

  private int color; 

  private int icon; 

  public int getPostion() {
   return postion;
  } 

  public void setPostion(int postion) {
   this.postion = postion;
  } 

  public float getValuse() {
   return valuse;
  } 

  public void setValuse(float valuse) {
   this.valuse = valuse;
  } 

  public int getColor() {
   return color;
  } 

  public void setColor(int color) {
   this.color = color;
  } 

  public int getIcon() {
   return icon;
  } 

  public void setIcon(int icon) {
   this.icon = icon;
  }
 } 

 class startAndRoatData { 

  private int postion; 

  private float startAng; 

  private float roatAng; 

  public startAndRoatData(int postion, float startAng, float roatAng) {
   this.postion = postion;
   this.startAng = startAng;
   this.roatAng = roatAng;
  } 

  public int getPostion() {
   return postion;
  } 

  public void setPostion(int postion) {
   this.postion = postion;
  } 

  public float getStartAng() {
   return startAng;
  } 

  public void setStartAng(float startAng) {
   this.startAng = startAng;
  } 

  public float getRoatAng() {
   return roatAng;
  } 

  public void setRoatAng(float roatAng) {
   this.roatAng = roatAng;
  } 

  @Override
  public String toString() {
   return "startAndRoatData{" + "postion=" + postion + ", startAng=" + startAng + ", roatAng=" + roatAng + '}';
  }
 }
}

用法如下:

SelectPieView mPie = (SelectPieView) findViewById(R.id.pie);
mPie.setCallBack(new SelectPieView.SelectPieCallBack() {
 @Override
 public void currentPostion(int postion) {
  Toast.makeText(CustomViewActivity.this, "postion="+postion, Toast.LENGTH_SHORT).show();
 }
});
ArrayList<SelectPieView.PieData> datas = new ArrayList<>();
datas.add(new SelectPieView.PieData(1, 200.3f, R.color.read_color, R.drawable.arrow));
datas.add(new SelectPieView.PieData(2, 200.3f, R.color.hx_red, R.drawable.arrow));
datas.add(new SelectPieView.PieData(3, 200.3f, R.color.text_blue, R.drawable.arrow));
mPie.reSetData(datas);
mPie.setNumber("333.33");

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android app第三方支付宝支付接入教程

    支付宝的接入相对比较简单,看看支付宝官网的文档基本都能搞定,但是切记一点让你们的后台也要搞清楚支付宝的流程,重中之重. 1.注意事项 开发前一定要阅读支付宝官方文档 强烈建议签名等处理在后台处理,我这个是测试是在自己本地写的,不要吐槽 想获取支付宝合作商户ID,及支付宝公钥请点击支付宝链接,生成密钥及PKCS8转码工具在文档中 添加Android.permission.INTERNET权限和android.permission.ACCESS_NETWORK_STATE权限 要导入支付宝的包 2.

  • Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效

    今年春节晚会没看尽兴,被支付宝集福给添了一段插曲,朋友们都在那数定时间段不停的咻一咻,哇,我咻到一个敬业福,不可能的,哈哈.那么咻一咻功能基于程序代码是怎么实现的呢?下面我们小编给大家分享本教程帮助大家学习Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效,具体内容如下所示: 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术不行,也太懒了 PS:这个view也是我模仿了人家的效果,参考了人家的思路写的,不是纯手撸,罪过罪过

  • Android仿支付宝的头部伸缩动画效果

    Android5.0推出的MaterialDesign库包含了处理头部工具栏的多个控件,不但允许自定义顶部导航栏,而且导航栏高度是可以伸缩的.如此一来,一方面导航栏能够放得下更多控件,另一方面在用户想看具体内容时也能腾出更多的屏幕空间. 这么说可能比较抽象,那就先来看看两张导航栏的效果图,第一张是导航栏完全展开时的界面,此时页面头部的导航栏占据了较大部分的高度: 第二张是导航栏完全收缩时的界面,此时头部导航栏只剩矮矮的一个长条. 看起来很眼熟是不是,上面的截图正是仿支付宝首页的头部效果.如果你熟

  • RecyclerView实现仿支付宝应用管理

    前言 由于公司项目有一个应用管理的功能和支付宝的应用管理功能非常像,所有的信息都是从服务端拉去的数据动态生成,有不同的应用分类,有标题等等信息.对于实现这种效果可以用ListView 或者RecyclerView通过加载多种布局来实现.我们首先需要分析怎么把效果图拆分成几种布局 效果图 从上面的图片中我们可以把布局分为三种类型,其中第一种布局le是 第二种布局类型是: 第三种布局类型 使用RecyclerView加载多种布局,很多人都会,但是这里每排显示的子应用数量是不同的,而所有的数据都是来自

  • Android中RecyclerView布局代替GridView实现类似支付宝的界面

    单纯使用GridView 通用的两种给GridView 添加分割线的方法:http://stackoverflow.com/questions/7132030/android-gridview-draw-dividers 给Gridview 添加分割线,也就是实现网格布局,不清楚谷歌为什么没有给Gridview 添加一个类似 ListView 的Divider 属性,因此就需要我们自己去添加分割线, 目前两种方法,第一种是 利用GridView 的  android:horizontalSpac

  • Android仿支付宝支付从底部弹窗效果

    我们再用支付宝支付的时候,会从底部弹上来一个对话框,让我们选择支付方式等等,今天我们就来慢慢实现这个功能 效果图 实现 主界面很简单,就是一个按钮,点击后跳到支付详情的Fragment中 package com.example.hfs.alipayuidemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.wi

  • Android接入支付宝实现支付功能实例

    我本来是想直接讲Android支付这一块的,包括支付宝,微信,其他第三方整合支付等,但是微信开放平台他对我的账号做了限制,所有我今天就先把重心放在支付宝的支付上,也算是写得尽可能详细些吧,毕竟是第三方的SDK,只要我们耐心的阅读文档和开发引导,这个其实不是很难的,我也是没有用过支付宝的支付,但是我相信,你看完这篇博客,也会对他了如指掌的,好的,我们正文开始 一.准备步骤 1.登录官网 他的官网就是蚂蚁金服的开放平台了,我们可以访问 蚂蚁金服开放平台 ,并且注册账号进行登录 创建应用 如果你是现有

  • Android使用view仿支付宝月账单

    前言 昨夜同门云集推杯又换盏,今朝茶凉酒寒豪言成笑谈.半生累,尽徒然,碑文完美有谁看,隐居山水之间誓与浮名散. 简介 今天给大家带来的是支付宝的月账单view的实现,看到标题,你可能会觉得是自定义view的相关实现,这里可能要让你失望了,因为这里我们用的是github上的一个开源项目. 1. 效果图 2. MPAndroidChart 我们用的是MPAndroidChart打开链接来实现的效果,它可以实现柱状图,饼状图等. 使用方法 1. 添加依赖 你可以选择在build.gradle中添加依赖

  • Android支付宝和微信支付集成

    场景 随着移动支付的兴起,在我们的app'中,会经常有集成支付的需求.这时候一般都会采用微信和支付宝的sdk 来集成 (一)支付宝支付 在使用支付宝支付的过程中,我们是在服务器端生成订单,客户端访问接口,并得到订单信息,调用接口支付,支付成功后支付宝会分别 异步调用服务器端,并向客户端返回支付结果. 开发步骤: ①注册支付宝账号--进行实名认证--提交审核资料--审核通过 支付宝无线快捷支付接口: b.alipay.com/order/productDetail.htm?productId=20

  • Android自定义控件实现支付宝记账饼图

    本文实例为大家分享了Android实现支付宝记账饼图,点击旋转到最下面,供大家参考,具体内容如下 代码: package com.example.a_102.myapplication7.ui; import java.util.ArrayList; import java.util.List; import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.

  • android自定义控件创建翻页接口详细代码

    本文分享的这个类的目的是为在看书翻页时,需要进行的动作提供接口,利用android自定义控件创建翻页接口,具体内容如下 BookPage.java package com.horse.util; import java.text.DecimalFormat; import java.util.Vector; import com.horse.bean.Chapter; import android.graphics.Bitmap; import android.graphics.Canvas;

  • Android自定义控件之基本原理(一)

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自定义控件要求: 1. 应当遵守Android标准的规范(命名,可配置,事件处理等). 2. 在XML布局中科配置控件的属性. 3. 对交互应当有合适的反馈,比如按下,点击等. 4. 具有兼容性, Android版本很多,应该具有广泛的适用性. 自定义控件学习步骤: 1 .View的工作原理 2 .编

  • Android自定义控件实现验证码倒计时

    今天给大家带来一个新的控件--验证码倒计时,先看下效果图 1 效果演示 2 使用方式 <com.landptf.view.CountDownM android:id="@+id/cdm_identifying_code" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_alignParentRight="true&quo

  • 详解Android自定义控件属性TypedArray以及attrs

    最近在研究android自定义控件属性,学到了TypedArray以及attrs.大家也可以结合<理解Android中的自定义属性>这篇文章进行学习,后续一篇还有应用. 1.attrs文件编写 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> &

  • Android自定义控件属性详细介绍

     Android自定义控件属性详细介绍 1. reference:参考某一资源ID.  (1)属性定义: <declare-styleable name = "名称"> <attr name = "background" format = "reference" /> </declare-styleable> (2)属性使用: <ImageView android:layout_width = "

  • Android 自定义控件实现显示文字的功能

    Android 自定义控件实现显示文字的功能 自定义控件-–逐个显示文字 ONE Goal ,ONE Passion ! 前言: 今天要实现的效果时.让我们的文字一个一个显示出来.上效果图吧: 实现原理: 1,拿到要显示的文字. 2,计算文字显示的速率 字体显示的速度 v = 总的字体长度 / 总的显示时间 3,将文字根据速率显示到控件上. 自定义View: public class printTextView extends TextView { /** * 字体显示出来的时间 */ priv

  • Android自定义控件深入学习 Android生成随机验证码

    在上一篇的文章中介绍了自定义控件的属性,详情见<详解Android自定义控件属性TypedArray以及attrs>.那么在这基础上实现随机验证码生成,里面的代码是自定义控件以及涉及到自定义view绘画. 1.先看实现的效果图 看到这个效果图是不是感觉还可以.那么就看看源码吧. 2.attr文件 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name=&qu

  • Android自定义控件eBook实现翻书效果实例详解

    本文实例讲述了Android自定义控件eBook实现翻书效果的方法.分享给大家供大家参考,具体如下: 效果图: Book.java文件: package com.book; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ImageView; public class Book extend

  • Android自定义控件基本原理详解(一)

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自定义控件要求: 1. 应当遵守Android标准的规范(命名,可配置,事件处理等).      2. 在XML布局中科配置控件的属性.      3. 对交互应当有合适的反馈,比如按下,点击等.      4. 具有兼容性, Android版本很多,应该具有广泛的适用性. 自定义控件学习步骤: 1

随机推荐