Android 开发订单流程view实例详解

 Android 开发订单流程view实例详解

先看看最终效果图:

怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有啊,但是最简单的就是通过自定义view来实现了~接下来让我们来实现下这个(订单流程view)。

首先我们定义好我们的自定义属性:

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="ProcessView">
    <!--滑动圆点的半径-->
    <attr name="thumb_radius" format="dimension"/>
    <!--到达的颜色-->
    <attr name="color_reached" format="color"/>
    <!--未到达的颜色-->
    <attr name="color_unreached" format="color"/>
    <!--textsize的大小-->
    <attr name="textsize" format="dimension"/>
    <!--text的颜色-->
    <attr name="text_color" format="color"/>
    <!--线的宽度-->
    <attr name="line_width" format="dimension"/>
    <!--状态文字数组-->
    <attr name="texts" format="reference"/>
  </declare-styleable>
</resources>

然后就是我们的老套路了,创建一个叫ProcessView的类继承view,然后定义好我们需要的属性:

/**
 * Created by leo on 17/3/27.
 */

public class ProcessView extends View {
  /**
   * 默认线宽度
   */
  private static final float D_LINE_WIDTH = 3;
  /**
   * 默认滑动圆点半径
   */
  private static final float D_THUMB_RADIUS = 10;
  /**
   * 默认textsize
   */
  private static final float D_TEXT_SIZE = 13f;
  private static final int D_REACH_COLOR = 0xFFF1AE0D;
  private static final int D_UNREACH_COLOR = Color.WHITE;
  private static final int D_TEXT_COLOR = Color.WHITE;

  private Paint linePaint;
  private TextPaint textPaint;
  private Paint thumbPaint;

  private float mTextSize = xx2px(TypedValue.COMPLEX_UNIT_SP, D_TEXT_SIZE);
  private float mLineWidth = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_LINE_WIDTH);
  private float mThumbRadius = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_THUMB_RADIUS);
  private int mReachedColor = D_REACH_COLOR;
  private int mUnreachedColor = D_UNREACH_COLOR;
  private int mTextColor = D_TEXT_COLOR;

  //当前进度
  private float mProgress = 0.0f;
  //所有的状态文字
  private String[] texts;

  public ProcessView(Context context) {
    this(context, null);
  }

  public ProcessView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public ProcessView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    obtainStyledAttrs(context, attrs, defStyleAttr);
    initViews();
  }

  /**
   * 获取我们的自定义属性
   * @param context
   * @param attrs
   * @param defStyleAttr
   */
  private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProcessView, defStyleAttr, 0);
    texts = a.hasValue(R.styleable.ProcessView_texts) ?
        getResources().getStringArray(a.getResourceId(R.styleable.ProcessView_texts, 0)) : texts;
    mLineWidth = a.hasValue(R.styleable.ProcessView_line_width) ?
        a.getDimensionPixelSize(R.styleable.ProcessView_line_width, 0) : mLineWidth;
    mThumbRadius = a.hasValue(R.styleable.ProcessView_thumb_radius) ?
        a.getDimensionPixelSize(R.styleable.ProcessView_thumb_radius, 0) : mThumbRadius;
    mTextSize = a.hasValue(R.styleable.ProcessView_textsize) ?
        a.getDimensionPixelSize(R.styleable.ProcessView_text_color, 0) : mTextSize;
    mReachedColor=a.hasValue(R.styleable.ProcessView_color_reached)?
        a.getColor(R.styleable.ProcessView_color_reached,D_REACH_COLOR):D_REACH_COLOR;
    mUnreachedColor=a.hasValue(R.styleable.ProcessView_color_unreached)?
        a.getColor(R.styleable.ProcessView_color_unreached,D_UNREACH_COLOR):D_UNREACH_COLOR;
    mTextColor=a.hasValue(R.styleable.ProcessView_text_color)?
        a.getColor(R.styleable.ProcessView_text_color,D_TEXT_COLOR):D_TEXT_COLOR;
    a.recycle();
  }

  /**
   * 初始化一些对象
   */
  private void initViews() {
    linePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    linePaint.setStyle(Paint.Style.FILL);
    textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    thumbPaint = new Paint(linePaint);

    textPaint.setTextSize(mTextSize);
    textPaint.setColor(mTextColor);
    linePaint.setStrokeWidth(mLineWidth);

  }
 }

然后就是重写我们的onmeasure方法了,我们这里就不考虑控件的高度为wrap_content这种情况了,所以我们只需要测量高度就可以了:

 @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightM = MeasureSpec.getMode(heightMeasureSpec);
    int defaultW = MeasureSpec.getSize(widthMeasureSpec);
    int defaultH = MeasureSpec.getSize(heightMeasureSpec);
    int resultW, resultH;
    resultW = defaultW;
    resultH = getDefaultHeight(defaultH, heightM);
    setMeasuredDimension(resultW, resultH);
  }

  private int getDefaultHeight(int height, int mode) {
    int result;
    if (mode == MeasureSpec.EXACTLY) {
      result = height;
    } else {
      //获取文字的高度
      float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
      //高度=圆半径+2.2*线条宽度(也就是竖线高度)+文字高度*1.3(也就是空隙高度)+0.5*文字高度
      result = (int) (mThumbRadius + mLineWidth * 2.2f + textH * 1.3f + 0.5 * textH);
    }
    return result;
  }

接着就是我们的核心方法onDraw()了,代码很简单都有注释,我就不一一解释了:

@Override
  protected void onDraw(Canvas canvas) {
    //画底部的竖线跟文字
    drawFoot(canvas);
    //画移动的小圆点跟进度条
    drawProgressAndThumb(canvas);
  }

  /**
   * 画底部的竖线跟文字
   */
  private void drawFoot(Canvas canvas) {
    //设置底部竖线宽度(底部的竖线会比进度条的要小一点)
    float lineWidth = mLineWidth * 0.8f;
    linePaint.setStrokeWidth(mLineWidth * 0.8f);
    //起始位置(也就是"订单已提交"的"已"字位置)
    float startX = textPaint.measureText(texts[0]) / 2;
    //结束的文字的位置("已送达"的"送"字位置)
    float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
    //绘制的终点位置
    float endX = getMeasuredWidth() - endTextW;
    //线条的总长度
    float lineW = (endX - startX) / (texts.length - 1);
    //竖线的高度
    float lineH = mLineWidth * 2.2f;
    //竖线的终点位置
    float lineY = mThumbRadius + mLineWidth / 2;
    //循环画出竖线跟文字
    for (int i = 0; i < texts.length; i++) {
      canvas.save();
      //每画一条竖线让画布水平平移linew个宽度
      canvas.translate(i * lineW, 0);
      //如果当前进度>竖线所在的位置,就改变竖线的颜色
      linePaint.setColor(i * lineW >= mProgress * (endX - startX) ? mUnreachedColor : mReachedColor);
      float endX2 = i == texts.length - 1 ? startX - lineWidth / 2 : startX + lineWidth / 2;
      canvas.drawLine(endX2, lineY, endX2, lineY + lineH, linePaint);

      //画文字
      textPaint.setTextAlign(Paint.Align.CENTER);
      float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
      canvas.drawText(texts[i], endX2, lineY + lineH + textH * 1.3f, textPaint);
      canvas.restore();
    }
  }

  private void drawProgressAndThumb(Canvas canvas) {
    float startX = textPaint.measureText(texts[0]) / 2;
    float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
    float endX = getMeasuredWidth() - endTextW;
    float lineY = mThumbRadius;
    linePaint.setStrokeWidth(mLineWidth);
    //draw basic line
    linePaint.setColor(mUnreachedColor);
    canvas.drawLine(startX, lineY, endX, lineY, linePaint);
    //draw progress line
    float progressX = startX + (endX - startX) * mProgress;
    linePaint.setColor(mReachedColor);
    canvas.drawLine(startX, lineY, progressX, lineY, linePaint);
    //给移动圆点一个RadialGradient颜色梯度效果
    thumbPaint.setShader(new RadialGradient(progressX, mThumbRadius, mThumbRadius, new int[]{Color.WHITE, D_REACH_COLOR, Color.YELLOW}, null, Shader.TileMode.REPEAT));
    canvas.drawCircle(progressX, mThumbRadius, mThumbRadius, thumbPaint);
  }

好啦~~然后我们暴露一个方法给外部,修改progress:

 public void setProgress(float progress) {
    if (progress != mProgress) {
      mProgress = progress;
      if (Looper.myLooper() == Looper.getMainLooper()) {
        invalidate();
      } else {
        postInvalidate();
      }
    }
  }

最后我们就可以跑起来了:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:id="@+id/activity_main"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:background="#b2000000"
  android:orientation="vertical"
  >
  <android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="5dp"
    app:cardElevation="3dp"
    app:cardBackgroundColor="#FF2384DD"
    >
    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      android:padding="10dp"
      >
      <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="商家已接单"
        android:textSize="14.5sp"
        android:textColor="#FFF1AE0D"
        />
      <TextView
        android:layout_marginTop="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="订单超过12小时自动完成"
        android:textSize="13sp"
        android:textColor="#fff"
        />
      <View
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@drawable/bg_line"
        android:layerType="software"
        />
      <com.yasin.processdemo.view.ProcessView
        android:id="@+id/id_process"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:texts="@array/process_states"
        />
    </LinearLayout>
  </android.support.v7.widget.CardView>
</LinearLayout>

arrays.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <array name="process_states">
    <item>订单已提交</item>
    <item>已付款</item>
    <item>商家已接单</item>
    <item>已送达</item>
  </array>
</resources>

然后是我们的测试activity:

package com.yasin.processdemo;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.AccelerateDecelerateInterpolator;

import com.yasin.processdemo.view.ProcessView;

public class MainActivity extends AppCompatActivity {
  private ProcessView mProcessView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mProcessView= (ProcessView) findViewById(R.id.id_process);
    startAni();
  }
  private void startAni() {
    ValueAnimator a = ValueAnimator.ofFloat(0, 1);
    a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        float progress = (float) animation.getAnimatedValue();
        mProcessView.setProgress(progress);
      }
    });
    a.setDuration(10000);
    a.setInterpolator(new AccelerateDecelerateInterpolator());
    a.start();
  }
}

最后附上processview的全部代码:

package com.yasin.processdemo.view;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.os.Looper;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import com.yasin.processdemo.R;

/**
 * Created by leo on 17/3/27.
 */

public class ProcessView extends View {
  /**
   * 默认线宽度
   */
  private static final float D_LINE_WIDTH = 3;
  /**
   * 默认滑动圆点半径
   */
  private static final float D_THUMB_RADIUS = 10;
  /**
   * 默认textsize
   */
  private static final float D_TEXT_SIZE = 13f;
  private static final int D_REACH_COLOR = 0xFFF1AE0D;
  private static final int D_UNREACH_COLOR = Color.WHITE;
  private static final int D_TEXT_COLOR = Color.WHITE;

  private Paint linePaint;
  private TextPaint textPaint;
  private Paint thumbPaint;

  private float mTextSize = xx2px(TypedValue.COMPLEX_UNIT_SP, D_TEXT_SIZE);
  private float mLineWidth = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_LINE_WIDTH);
  private float mThumbRadius = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_THUMB_RADIUS);
  private int mReachedColor = D_REACH_COLOR;
  private int mUnreachedColor = D_UNREACH_COLOR;
  private int mTextColor = D_TEXT_COLOR;

  //当前进度
  private float mProgress = 0.0f;
  //所有的状态文字
  private String[] texts;

  public ProcessView(Context context) {
    this(context, null);
  }

  public ProcessView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public ProcessView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    obtainStyledAttrs(context, attrs, defStyleAttr);
    initViews();
  }

  /**
   * 获取我们的自定义属性
   * @param context
   * @param attrs
   * @param defStyleAttr
   */
  private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProcessView, defStyleAttr, 0);
    texts = a.hasValue(R.styleable.ProcessView_texts) ?
        getResources().getStringArray(a.getResourceId(R.styleable.ProcessView_texts, 0)) : texts;
    mLineWidth = a.hasValue(R.styleable.ProcessView_line_width) ?
        a.getDimensionPixelSize(R.styleable.ProcessView_line_width, 0) : mLineWidth;
    mThumbRadius = a.hasValue(R.styleable.ProcessView_thumb_radius) ?
        a.getDimensionPixelSize(R.styleable.ProcessView_thumb_radius, 0) : mThumbRadius;
    mTextSize = a.hasValue(R.styleable.ProcessView_textsize) ?
        a.getDimensionPixelSize(R.styleable.ProcessView_text_color, 0) : mTextSize;
    mReachedColor=a.hasValue(R.styleable.ProcessView_color_reached)?
        a.getColor(R.styleable.ProcessView_color_reached,D_REACH_COLOR):D_REACH_COLOR;
    mUnreachedColor=a.hasValue(R.styleable.ProcessView_color_unreached)?
        a.getColor(R.styleable.ProcessView_color_unreached,D_UNREACH_COLOR):D_UNREACH_COLOR;
    mTextColor=a.hasValue(R.styleable.ProcessView_text_color)?
        a.getColor(R.styleable.ProcessView_text_color,D_TEXT_COLOR):D_TEXT_COLOR;
    a.recycle();
  }

  /**
   * 初始化一些对象
   */
  private void initViews() {
    linePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    linePaint.setStyle(Paint.Style.FILL);
    textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    thumbPaint = new Paint(linePaint);

    textPaint.setTextSize(mTextSize);
    textPaint.setColor(mTextColor);
    linePaint.setStrokeWidth(mLineWidth);

  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightM = MeasureSpec.getMode(heightMeasureSpec);
    int defaultW = MeasureSpec.getSize(widthMeasureSpec);
    int defaultH = MeasureSpec.getSize(heightMeasureSpec);
    int resultW, resultH;
    resultW = defaultW;
    resultH = getDefaultHeight(defaultH, heightM);
    setMeasuredDimension(resultW, resultH);
  }

  private int getDefaultHeight(int height, int mode) {
    int result;
    if (mode == MeasureSpec.EXACTLY) {
      result = height;
    } else {
      //获取文字的高度
      float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
      //高度=圆半径+2.2*线条宽度(也就是竖线高度)+文字高度*1.3(也就是空隙高度)+0.5*文字高度
      result = (int) (mThumbRadius + mLineWidth * 2.2f + textH * 1.3f + 0.5 * textH);
    }
    return result;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    //画底部的竖线跟文字
    drawFoot(canvas);
    //画移动的小圆点跟进度条
    drawProgressAndThumb(canvas);
  }

  /**
   * 画底部的竖线跟文字
   */
  private void drawFoot(Canvas canvas) {
    //设置底部竖线宽度(底部的竖线会比进度条的要小一点)
    float lineWidth = mLineWidth * 0.8f;
    linePaint.setStrokeWidth(mLineWidth * 0.8f);
    //起始位置(也就是"订单已提交"的"已"字位置)
    float startX = textPaint.measureText(texts[0]) / 2;
    //结束的文字的位置("已送达"的"送"字位置)
    float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
    //绘制的终点位置
    float endX = getMeasuredWidth() - endTextW;
    //线条的总长度
    float lineW = (endX - startX) / (texts.length - 1);
    //竖线的高度
    float lineH = mLineWidth * 2.2f;
    //竖线的终点位置
    float lineY = mThumbRadius + mLineWidth / 2;
    //循环画出竖线跟文字
    for (int i = 0; i < texts.length; i++) {
      canvas.save();
      //每画一条竖线让画布水平平移linew个宽度
      canvas.translate(i * lineW, 0);
      //如果当前进度>竖线所在的位置,就改变竖线的颜色
      linePaint.setColor(i * lineW >= mProgress * (endX - startX) ? mUnreachedColor : mReachedColor);
      float endX2 = i == texts.length - 1 ? startX - lineWidth / 2 : startX + lineWidth / 2;
      canvas.drawLine(endX2, lineY, endX2, lineY + lineH, linePaint);

      //画文字
      textPaint.setTextAlign(Paint.Align.CENTER);
      float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
      canvas.drawText(texts[i], endX2, lineY + lineH + textH * 1.3f, textPaint);
      canvas.restore();
    }
  }

  private void drawProgressAndThumb(Canvas canvas) {
    float startX = textPaint.measureText(texts[0]) / 2;
    float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
    float endX = getMeasuredWidth() - endTextW;
    float lineY = mThumbRadius;
    linePaint.setStrokeWidth(mLineWidth);
    //draw basic line
    linePaint.setColor(mUnreachedColor);
    canvas.drawLine(startX, lineY, endX, lineY, linePaint);
    //draw progress line
    float progressX = startX + (endX - startX) * mProgress;
    linePaint.setColor(mReachedColor);
    canvas.drawLine(startX, lineY, progressX, lineY, linePaint);
    //给移动圆点一个RadialGradient颜色梯度效果
    thumbPaint.setShader(new RadialGradient(progressX, mThumbRadius, mThumbRadius, new int[]{Color.WHITE, D_REACH_COLOR, Color.YELLOW}, null, Shader.TileMode.REPEAT));
    canvas.drawCircle(progressX, mThumbRadius, mThumbRadius, thumbPaint);
  }

  public void setProgress(float progress) {
    if (progress != mProgress) {
      mProgress = progress;
      if (Looper.myLooper() == Looper.getMainLooper()) {
        invalidate();
      } else {
        postInvalidate();
      }
    }
  }

  private float xx2px(int unit, float value) {
    Context c = getContext();
    Resources r;
    if (c == null)
      r = Resources.getSystem();
    else
      r = c.getResources();
    return (TypedValue.applyDimension(
        unit, value, r.getDisplayMetrics()));
  }
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Android 开发订单流程view实例详解

     Android 开发订单流程view实例详解 先看看最终效果图: 怎么样,效果还是很不错的吧?群里有人说切四张图的.recycleview的.各种的都有啊,但是最简单的就是通过自定义view来实现了-接下来让我们来实现下这个(订单流程view). 首先我们定义好我们的自定义属性: attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleabl

  • Android开发之浏览器用法实例详解(调用uc,opera,qq浏览器访问网页)

    本文实例讲述了Android开发之浏览器用法.分享给大家供大家参考,具体如下: 一.启动android默认浏览器 Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); Uri content_url = Uri.parse("http://www.jb51.net"); intent.setData(content_url); startActivity(inten

  • Android 控制ScrollView滚动的实例详解

    Android 控制ScrollView滚动的实例详解 在开发中,我们经常需要更新列表,并将列表拉倒最底部,比如发表微博,聊天界面等等, 这里有两种办法,第一种,使用scrollTo(): public static void scrollToBottom(final View scroll, final View inner) { Handler mHandler = new Handler(); mHandler.post(new Runnable() { public void run()

  • Android Adapter里面嵌套ListView实例详解

    Android Adapter里面嵌套ListView实例详解 前言: 可嵌套~但是显示需要特殊处理下~以下是处理方法 前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个ListItem中放入另外一个ListView.但刚开始的时候,会发现放入的小ListView会显示不完全,它的高度始终有问题.上网查了下,发现别人也有遇到这样的问题,而大多数人都不推荐这样的设计,因为默认情况下Android是禁止在ScrollView中放入另外的Scr

  • Android中mvp模式使用实例详解

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller. 在MVC里,View是可以直接访问

  • Android 中读取Excel文件实例详解

    Android 中读取Excel文件实例详解 最近有个需求需要在app内置数据,新来的产品扔给了我两个Excel表格就不管了(两个表格格式还不统一...),于是通过度娘等方法找到了Android中读取Excel表格文件的一种方法,记录一下. 闲话一下Excel中工作簿和工作表的区别: 工作簿中包含有工作表.工作簿可以由一张或多张工作表组成,一个工作簿就是一个EXCEL表格文件. 好了,开始读取表格文件吧. 前提 首先,我们假设需要读取的表格文件名字为test.xls, 位于assets根目录下.

  • Android 打包三种方式实例详解

     Android 打包三种方式实例详解 前言: 现在市场上很多app应用存在于各个不同的渠道,大大小小几百个,当我们想要在发布应用之后统计各个渠道的用户下载量,我们就要进行多渠道打包. 01.应用的打包签名什么是打包? 打包就是根据签名和其他标识生成安装包. 签名是什么? 1.在android应用文件(apk)中保存的一个特别字符串 2.用来标识不同的应用开发者:开发者A,开发者B 3.一个应用开发者开发的多款应用使用同一个签名 就好比是一个人写文章,签名就相当于作者的署名. 如果两个应用都是一

  • Android 逐帧动画创建实例详解

    Android 逐帧动画创建实例详解 前言: 我们看早期电影的时候,电影通常是一张一张播放,用我们现在专有名词来说,就是一帧帧来,安卓同样有这样动画效果的编排形式. 那么我们先定义逐帧动画xml文件 <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" an

  • Android 中 Tweened animation的实例详解

    Android 中 Tweened animation的实例详解 Tweened animation有四种类型,下面主要介绍Scale类型. 运行效果如下: Android SDK提供了2种方法:直接从XML资源中读取Animation,使用Animation子类的构造函数来初始化Animation对象,第二种方法在看了Android SDK中各个类的说明就知道如何使用了,下面简要说明从XML资源中读取Animation.XML资源中的动画文件animation.xml内容为: <?xml ve

  • Android 滑动监听的实例详解

    Android 滑动监听的实例详解 摘要: ScollBy,ScollTo是对内容的移动,view.ScollyBy是对view的内容的移动 view,ScollTo是对内容的移动(移动到指定位置),view.ScollyBy是对view的内容的移动(移动距离) 在次activity中,当手指点击TextView ,此时是ViewGroup 响应还是TextView响应呢? 代码实践: 在activity中重写onTouchEvent(): public boolean onTouchEvent

随机推荐