Android日志系统,Android Studio中获取SHA1或MD5的方法

2015/8/17问题集

Android日志系统

这个类比较常用的打印日志的方法有5个,这5个方法都会把日志打印到LogCat中:

  • Log.v(tag,message); //verbose模式,打印最详细的日志
  • Log.d(tag,message); //debug级别的日志
  • Log.i(tag,message); //info级别的日志
  • Log.w(tag,message); //warn级别的日志
  • Log.e(tag,message); //error级别的日志

其中tag和message分别是两个String值.从android开发帮助文档中来看,tag和message的定义分别是:

  • tag : Used to identify the source of a log message. It usually identifies the class or activity where the log call occurs.
  • msg : The message you would like logged.

可看出tag用来标记log消息的源头的.而message则是这条log的内容.

从日志的输出数量来算,error,warn,info,debug,verbose,数量从少到多.

Android Studio中获取SHA1或MD5的方法

第一步、打开Android Studio的Tools->Open Terminal…

第二步、输入命令:keytool -v -list -keystore keystore.jks

【一定要记得加上 -v 参数,不然只能看到SHA1,没有MD5】【keystore.jks,需要替换为你自己的密钥所在路径和文件名】

聚合数据API使用

2015/8/16问题集

聚合数据API使用

MainActivity里的代码:使用的时候只需要更改Parameters

package com.thinkland.juheapi.demo;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.thinkland.sdk.android.DataCallBack;
import com.thinkland.sdk.android.JuheData;
import com.thinkland.sdk.android.Parameters;

public class MainActivity extends Activity {

private Context mContext;
TextView tv;
private Button btn,btnWeather;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mContext = this;
    tv = (TextView) findViewById(R.id.tv);



    /**
     * 请不要添加key参数.
     */
    Parameters params = new Parameters();
    params.add("ip", "www.juhe.cn");
    params.add("dtype", "xml");
    /**
     * 请求的方法 参数: 第一个参数 当前请求的context;
     *                   第二个参数 接口id;
     *                   第三个参数 接口请求的url;
     *                   第四个参数 接口请求的方式;
     *                   第五个参数 接口请求的参数,键值对com.thinkland.sdk.android.Parameters类型;
     *                   第六个参数请求的回调方法,com.thinkland.sdk.android.DataCallBack;
     * 
     */
    JuheData.executeWithAPI(mContext, 1, "http://apis.juhe.cn/ip/ip2addr",
            JuheData.GET, params, new DataCallBack() {
                /**
                 * 请求成功时调用的方法 statusCode为http状态码,responseString为请求返回数据.
                 */
                @Override
                public void onSuccess(int statusCode, String responseString) {
                    // TODO Auto-generated method stub
                    tv.append(responseString + "\n");
                }

                /**
                 * 请求完成时调用的方法,无论成功或者失败都会调用.
                 */
                @Override
                public void onFinish() {
                    // TODO Auto-generated method stub
                    Toast.makeText(getApplicationContext(), "finish",
                            Toast.LENGTH_SHORT).show();
                }

                /**
                 * 请求失败时调用的方法,statusCode为http状态码,throwable为捕获到的异常
                 * statusCode:30002 没有检测到当前网络.
                 *               30003 没有进行初始化.
                 *               0 未明异常,具体查看Throwable信息.
                 *               其他异常请参照http状态码.
                 */
                @Override
                public void onFailure(int statusCode,
                        String responseString, Throwable throwable) {
                    // TODO Auto-generated method stub
                    tv.append(throwable.getMessage() + "\n");
                }
            });

}

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    /**
     * 关闭当前页面正在进行中的请求.
     */
    JuheData.cancelRequests(mContext);
}

}

需要继承Application

package com.thinkland.juheapi.demo;

import com.thinkland.sdk.android.JuheSDKInitializer;

import android.app.Application;
import android.widget.Button;

public class MyApplication extends Application {



@Override
public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
    JuheSDKInitializer.initialize(getApplicationContext());

}
}

更改manifest的设置即可

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thinkland.juheapi.demo"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="9"
    android:targetSdkVersion="15" />

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<android:uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />
<android:uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />

<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <meta-data
        android:name="com.thinkland.juheapi.openid"
        android:value="JHf2946fb83e4a9d7dbd854fa65bd130b1" />

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".CaptchaActicity"
        android:label="@string/title_activity_captcha_acticity" >
    </activity>
    <activity
        android:name=".Captcha"
        android:label="@string/title_activity_captcha" >
    </activity>
    <activity
        android:name=".WeatherActivity"
        android:label="@string/title_activity_weather" >
    </activity>
</application>

</manifest>

Activity继承错误

错误代码提示:

java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

原因:
从错误提示中提到Theme.AppCompat theme,这是因为我们的activity一定是继承了兼容包中的类,
比如我这里就无意中继承了ActionBarActivity,它来自android.support.v7.app.ActionBarActivity。
所以就要使用与其配合的AppCompat的theme才行。

Android手机的通讯录

Android手机的通讯录

Android手机的通讯录联系人全部都存在系统的数据库中,如果须要获得通讯里联系人的信息就须要访问系统的数据库,才能将信息拿出来。

contacts 表

  • _id :表的ID,主要用于其它表通过contacts 表中的ID可以查到相应的数据。
  • display_name: 联系人名称
  • photo_id:头像的ID,如果没有设置联系人头像,这个字段就为空
  • times_contacted:通话记录的次数
  • last_time_contacted: 最后的通话时间
  • lookup :是一个持久化的储存 因为用户可能会改名子 但是它改不了lookup

简单实例

要先添加权限

<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>

这个简单实例只是把数据显示在控制台上。

package com.zsz.develop.getmyphonenumber;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;

/**
 * Created by shengzhong on 2015/8/15.
 */
public class GetNumber {

public static String getNumber(Context context){
    /**得到手机通讯录联系人信息**/
    ContentResolver resolver= context.getContentResolver();
    // 获取手机联系人
   Cursor phoneCursor= resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
    if (phoneCursor!=null){

        String phoneNumber;
        String phoneName;
        while (phoneCursor.moveToNext()){
            //得到手机号码和名字
             phoneNumber=phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            phoneName=phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));

            System.out.println("联系人:"+phoneName +"     电话号码:"+phoneNumber);
        }


    }


    return null;
}
}

把通讯录显示在页面上

MainActivity中的代码:主要加载页面信息

package com.zsz.develop.getmyphonenumber;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

import java.util.List;


public class MainActivity extends ActionBarActivity {
private ListView lv;
private MyAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    GetNumber.getNumber(this);

    lv= (ListView) findViewById(R.id.lv);
    adapter=new MyAdapter(GetNumber.lists,this);
    lv.setAdapter(adapter);
}
}

GetNumber中的代码主要获得通讯录信息

package com.zsz.develop.getmyphonenumber;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;

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

/**
 * Created by shengzhong on 2015/8/15.
 */
public class GetNumber {

public static List<PhoneInfo> lists=new ArrayList<PhoneInfo>();

public static String getNumber(Context context){
    /**得到手机通讯录联系人信息**/
    ContentResolver resolver= context.getContentResolver();
    // 获取手机联系人
   Cursor phoneCursor= resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
    if (phoneCursor!=null){

        String phoneNumber;
        String phoneName;
        while (phoneCursor.moveToNext()){
            //得到手机号码和名字
             phoneNumber=phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            phoneName=phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            PhoneInfo phoneInfo=new PhoneInfo(phoneName,phoneNumber);
            lists.add(phoneInfo);
            System.out.println("联系人:"+phoneName +"     电话号码:"+phoneNumber);
        }
    }
    return null;
}
}

PhoneInfo对数据进行封装

package com.zsz.develop.getmyphonenumber;

/**
 * Created by shengzhong on 2015/8/16.
 */
public class PhoneInfo {

   private String phoneName;
private String phoneNumber;

public PhoneInfo(String phoneName,String phoneNumber){
    setPhoneName(phoneName);
    setPhoneNumber(phoneNumber);
}


public String getPhoneName() {
    return phoneName;
}

public void setPhoneName(String phoneName) {
    this.phoneName = phoneName;
}

public String getPhoneNumber() {
    return phoneNumber;
}

public void setPhoneNumber(String phoneNumber) {
    this.phoneNumber = phoneNumber;
}
}

MyAdapter对listview进行适配。

package com.zsz.develop.getmyphonenumber;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by shengzhong on 2015/8/16.
 */
public class MyAdapter extends BaseAdapter {
private List<PhoneInfo> lists;
private Context context;
private LayoutInflater layoutInflater;
private LinearLayout layout;

public MyAdapter(List<PhoneInfo> lists, Context context){
    this.lists=lists;
    this.context=context;
}



@Override
public int getCount() {
    return lists.size();
}

@Override
public Object getItem(int i) {
    return lists.get(i);
}

@Override
public long getItemId(int i) {
    return i;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    layoutInflater=LayoutInflater.from(context);
    layout= (LinearLayout) layoutInflater.inflate(R.layout.call,null);
    TextView tvName= (TextView) layout.findViewById(R.id.tvName);
    TextView tvNumber= (TextView) layout.findViewById(R.id.tvNumber);
    tvName.setText(lists.get(i).getPhoneName());
    tvNumber.setText(lists.get(i).getPhoneNumber());

    return layout;
}
}

call的layout。在main中有一个list

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    >
    <ImageView
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:src="@drawable/jiamin"
        />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tvName"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tvNumber"
            />


    </LinearLayout>


</LinearLayout>

</LinearLayout>

listView优化

使用holder新建textview来操作。

重用了convertView,很大程度上的减少了内存的消耗。通过判断convertView是否为null,是的话就需要产生一个视图出来,然后给这个视图数据,最后将这个视图返回给底层,呈献给用户。
特点:如果当前的convertView为null,则通过LayoutInflat产生一个view。

其中converView会反复使用,目的是为了提高ListView效率。

package com.zsz.develop.getmyphonenumber;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by shengzhong on 2015/8/16.
 */
public class MyAdapter extends BaseAdapter {
private List<PhoneInfo> lists;
private Context context;
private LayoutInflater layoutInflater;
private LinearLayout layout;

public MyAdapter(List<PhoneInfo> lists, Context context){
    this.lists=lists;
    this.context=context;
}



@Override
public int getCount() {
    return lists.size();
}

@Override
public Object getItem(int i) {
    return lists.get(i);
}

@Override
public long getItemId(int i) {
    return i;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
//        layoutInflater=LayoutInflater.from(context);
//        layout= (LinearLayout) layoutInflater.inflate(R.layout.call,null);
//        TextView tvName= (TextView) layout.findViewById(R.id.tvName);
//        TextView tvNumber= (TextView) layout.findViewById(R.id.tvNumber);
//        tvName.setText(lists.get(i).getPhoneName());
//        tvNumber.setText(lists.get(i).getPhoneNumber());
//
    ViewHolder holder;
    if (view==null){
        view=LayoutInflater.from(context).inflate(R.layout.call,null);
        holder=new ViewHolder();
        holder.tvName= (TextView) view.findViewById(R.id.tvName);
        holder.tvNumber= (TextView) view.findViewById(R.id.tvNumber);
        holder.tvName.setText(lists.get(i).getPhoneName());
        holder.tvNumber.setText(lists.get(i).getPhoneNumber());
        view.setTag(holder);

    }else {
        holder= (ViewHolder) view.getTag();
        holder.tvName.setText(lists.get(i).getPhoneName());
        holder.tvNumber.setText(lists.get(i).getPhoneNumber());

    }

    return view;
}

private static class ViewHolder{

    TextView tvName;
    TextView tvNumber;
}
}

部署代码到CentOS云服务器

部署代码到CentOS云服务器

FTP通道

用户需要使用FTP通道,将应用程序从用户自己的服务器上传到云服务器上。

FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。此外,由于FTP传输效率非常高,在网络上传输大的文件时,一般也采用该协议。

默认情况下FTP协议使用TCP端口中的 20和21这两个端口,其中20用于传输数据,21用于传输控制信息。但是,是否使用20作为传输数据的端口与FTP使用的传输模式有关,如果采用主动模式,那么数据传输端口就是20;如果采用被动模式,则具体最终使用哪个端口要服务器端和客户端协商决定。

http://www.qcloud.com/wiki/%E9%83%A8%E7%BD%B2%E4%BB%A3%E7%A0%81%E5%88%B0CentOS%E4%BA%91%E6%9C%8D%E5%8A%A1%E5%99%A8

px和dp的转换公式, Android 判断当前线程是否是主线程的方法

2015/8/6问题集

px和dp的转换公式

px = dp * (dpi / 160)

  • px:即像素,1px代表屏幕上一个物理的像素点;px单位不被建议使用,因为同样100px的图片,在不同手机上显示的实际大小可能不同

  • dp:它与“像素密度”密切相关,所以首先我们解释一下什么是像素密度。假设有一部手机,屏幕的物理尺寸为1.5英寸x2英寸,屏幕分辨率为240x320,则我们可以计算出在这部手机的屏幕上,每英寸包含的像素点的数量为240/1.5=160dpi(横向)或320/2=160dpi(纵向),160dpi就是这部手机的像素密度,像素密度的单位dpi是Dots Per Inch的缩写,即每英寸像素数量。横向和纵向的这个值都是相同的,原因是大部分手机屏幕使用正方形的像素点。

  • 四种像素密度:而ldpi指120,mdpi指160,hdpi指240,xhdpi指320。低(120dpi)、中(160dpi)、高(240dpi)和超高(320dpi),它们对应的dp到px的系数分别为0.75、1、1.5和2,这个系数乘以dp长度就是像素数。例如界面上有一个长度为“80dp”的图片,那么它在240dpi的手机上实际显示为80x1.5=120px,在320dpi的手机上实际显示为80x2=160px

  • dip:
    与dp完全相同,只是名字不同而已。在早期的Android版本里多使用dip,后来为了与sp统一就建议使用dp这个名字了。

  • sp:
    与缩放无关的抽象像素(Scale-independent Pixel)。sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。

  • mm:
    即毫米;

  • in:
    即英寸,1英寸=2.54厘米(约);

  • pt:
    1pt=1/72英寸=0.035厘米;

最佳实践,文字的尺寸一律用sp单位,非文字的尺寸一律使用dp单位。例如textSize=”16sp”、layout_width=”60dp”;偶尔需要使用px单位,例如需要在屏幕上画一条细的分隔线时:

如何加载一张大图bitmap如(4096*4096)

加载一张大图,有什么注意事项

  • 在展示高分辨率图片的时候,最好先将图片进行压缩。压缩后的图片大小应该和用来展示它的控件大小相近,在一个很小的ImageView上显示一张超大的图片不会带来任何视觉上的好处,但却会占用我们相当多宝贵的内存,而且在性能上还可能会带来负面影响。

  • 为了避免OOM异常,最好在解析每张图片的时候都先检查一下图片的大小,除非你非常信任图片的来源,保证这些图片都不会超出你程序的可用内存。

Android 判断当前线程是否是主线程的方法

  • 方法一:使用Looper类判断

    Looper.myLooper() != Looper.getMainLooper()  
    

方法二:通过查看Thread类的当前线程

Thread.currentThread() == Looper.getMainLooper().getThread() 

方法三:使用线程句柄判断,将主线程的Thread.currentThread()获取到主线程当前句柄,保存起来,在需要判断的时候调用Thread.currentThread()来与之比较,即可判断当前线程是否是主线程了,该方法可以参见Activity中

private Thread mUiThread;  

public final void runOnUiThread(Runnable action) {  
    if (Thread.currentThread() != mUiThread) {  
        mHandler.post(action);  
    } else {  
        action.run();  
    }  
}  

android端乱码问题,RadioGroup多选一,对比空字符,4种方式实现java 保留2位小数点

2015/8/5问题集

android端乱码问题

服务器中没问题而单单android端乱码,那么一定是接收的时候出现问题

把这句代码

entity= EntityUtils.toString(response.getEntity());

改成接收的时候也要转成UTF-8

entity= EntityUtils.toString(response.getEntity(),"UTF-8");

RadioGroup多选一

程序中常常要用到多选一的时候,例如男女

就以男女为例

XML

 <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="性别:"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="男"
        android:id="@+id/etSex"
        />
    <!--<EditText-->
        <!--android:id="@+id/etSex"-->
        <!--android:layout_width="fill_parent"-->
        <!--android:layout_height="wrap_content"-->
        <!--/>-->

    </LinearLayout>
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RadioGroup android:id="@+id/radioGroup"
        android:contentDescription="性别"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/radioMale"
            android:text="男"
            android:checked="true">

        </RadioButton>
        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/radioFemale"
            android:text="女">

        </RadioButton>
    </RadioGroup>

    </LinearLayout>

Activty中的代码如下

etSex= (TextView) findViewById(R.id.etSex);

   radioGroup= (RadioGroup) findViewById(R.id.radioGroup);
   radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
       @Override
       public void onCheckedChanged(RadioGroup radioGroup, int i) {
        int radioButtonId = radioGroup.getCheckedRadioButtonId();
           rb = (RadioButton)EditDataActicity.this.findViewById(radioButtonId);
           etSex.setText( rb.getText());
       }
   });

对比空字符

对比空字符要用equals(“”)

etHeight.getText().toString().trim().equals("")

4种方式实现java 保留2位小数点

方式一:

四舍五入
double f = 111231.5585;
BigDecimal b = new BigDecimal(f);
double f1 = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
保留两位小数

方式二:

java.text.DecimalFormat df =new java.text.DecimalFormat(”#.00″);
df.format(你要格式化的数字);
例:new java.text.DecimalFormat(”#.00″).format(3.1415926)

(#.00 表示两位小数 #.0000四位小数 以此类推…

方式三:

double d = 3.1415926;
String result = String .format(”%.2f”);
%.2f %. 表示 小数点前任意位数 2 表示两位小数 格式后的结果为f 表示浮点型。

方式四:

此外如果使用struts标签做输出的话,有个format属性,设置为format=”0.00”就是保留两位小数
例如:

AChartEngine超简单实例

AChartEngine超简单实例

其实无非就在做三件事

  • 1.添加数据进图标
  • 2.线或条等设置
  • 3.制作成什么表。仅此而已

package com.zsz.develop.mychart02;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.Button;
import android.widget.LinearLayout;


import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import java.util.Random;

/**
 * Created by shengzhong on 2015/7/29.
 */
public class ShowExamActivity extends Activity{
private LinearLayout llChart;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {

    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.show_exam_activity);
    // 1, 构造显示用渲染图
    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
    // 2,进行显示
    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    // 2.1, 构建数据
    Random r = new Random();
    for (int i = 0; i < 2; i++) {
        XYSeries series = new XYSeries("test" + (i + 1));
        // 填充数据
        for (int k = 0; k < 10; k++) {
            // 填x,y值
            series.add(k, 20 + r.nextInt() % 100);
        }
        // 需要绘制的点放进dataset中
        dataset.addSeries(series);
    }
    // 3, 对点的绘制进行设置
    XYSeriesRenderer xyRenderer = new XYSeriesRenderer();
    // 3.1设置颜色
    xyRenderer.setColor(Color.BLUE);
    // 3.2设置点的样式
    xyRenderer.setPointStyle(PointStyle.SQUARE);
    // 3.3, 将要绘制的点添加到坐标绘制中
    renderer.addSeriesRenderer(xyRenderer);
    // 3.4,重复 1~3的步骤绘制第二个系列点
    xyRenderer = new XYSeriesRenderer();
    xyRenderer.setColor(Color.RED);
    xyRenderer.setPointStyle(PointStyle.CIRCLE);
    renderer.addSeriesRenderer(xyRenderer);
//        Intent intent = new LinChart().execute(this);
//        Intent intent = ChartFactory
//                .getLineChartIntent(this, dataset, renderer);
    GraphicalView graphicalView = ChartFactory.getLineChartView(this, dataset, renderer);
    llChart= (LinearLayout) findViewById(R.id.llChart);
    llChart.addView(graphicalView);
//                startActivity(intent);

}

}

详细配置。

上面的配置只配置了几个基础的,还要进行更多配置才能使得图标更加简单通熟易懂。

  • XYSeries: 最常用的数据结构,主要包括一系列的double型(x,y)点对及一个名称(title)。
  • XYValueSeries:包括一系列的(x,y,value)点对及一个名称(title)。
  • XYMultipleSeriesDataset:包含一系列XYSeries,是最终的数据结构
  • TimeSeries:与XYSeries类似,x变为Date型,可以转化为XYSeries。
  • CategorySeries:与XYSeries类似,x变为string型,可以转化为XYSeries。
  • MultipleCategorySeries:一系列CategorySeries。

  • XYSeriesRenderer,impleSeriesRenderer、用于设置每张图中每一个序列的绘制方法。- XYMultipleSeries,RendererDefaultRenderer用于设置整张图的绘制格式。

XYMultipleSeriesRenderer.setAxisTitleTextSize

详细配置

  • 1.修改背景色或设置背景图片:
    背景色设置需要设置两项:setMarginsColor(设置四边颜色)以及setBackgroundColor(设置中间背景色)
  • 设置背景图片:
    http://blog.csdn.net/kmyhy/article/details/6590294
    
  1. setAxisTitleTextSize(16);// 设置坐标轴标题文本大小
  2. setChartTitleTextSize(20); // 设置图表标题文本大小
  3. setLabelsTextSize(15); // 设置轴标签文本大小
  4. setLegendTextSize(15); // 设置图例文本大小
  5. renderer.setChartTitle( “个人收支表”);//设置柱图名称
  6. renderer.setXTitle( “名单” );//设置X轴名称
  7. renderer.setYTitle( “金额” );//设置Y轴名称
  8. renderer.setXAxisMin(0.5);//设置X轴的最小值为0.5
  9. renderer.setXAxisMax(5.5);//设置X轴的最大值为5
  10. renderer.setYAxisMin(0);//设置Y轴的最小值为0
  11. renderer.setYAxisMax(500);//设置Y轴最大值为500
  12. renderer.setDisplayChartValues(true);//设置是否在柱体上方显示值
  13. renderer.setShowGrid(true);//设置是否在图表中显示网格
  14. renderer.setXLabels(0);//设置X轴显示的刻度标签的个数
  15. 如果想要在X轴显示自定义的标签,那么首先要设置renderer.setXLabels(0); 如果不设置为0,那么所设置的Labels会与原X坐标轴labels重叠
    其次我们要renderer.addTextLabel()循环添加
    eg:for(int i=0;i<13;i++)
    {
    renderer.addTextLabel(i+1,years[i]); //循环添加Xlabel其中显示的label放在years数组中
    
    }
  16. renderer.setXLabelsAlign(Align.RIGHT);//设置刻度线与X轴之间的相对位置关系
  17. renderer.setYLabelsAlign(Align.RIGHT);//设置刻度线与Y轴之间的相对位置关系
  18. renderer.setZoomButtonsVisible(true);//设置可以缩放
  19. renderer.setPanLimits(newdouble[] { 0, 20, 0, 140 });//设置拉动的范围
  20. renderer.setZoomLimits(newdouble[] { 0.5, 20, 1, 150 });//设置缩放的范围
  21. renderer.setRange(newdouble[]{0d, 5d, 0d, 100d}); //设置chart的视图范围
  22. renderer.setFitLegend(true);// 调整合适的位置
  23. renderer.setClickEnabled(true)//设置是否可以滑动及放大缩小;
  24. Dataset和Render参数介绍:
    http://blog.csdn.net/lk_blog/article/details/7645661

  25. ChartView.repaint();是重新绘图的命令

  26. renderer.setMargins(new int[] { 70, 70, 100, 70 });//设置图表的外边框(上/左/下/右)

Android中图表AChartEngine

2015/7/29问题集

Android中图表AChartEngine

很多时候项目中我们需要对一些统计数据进行绘制表格,更多直观查看报表分析结果。基本有以下几种方法:

  • 1:可以进行android api进行draw这样的话,效率比较低

  • 2:使用开源绘表引擎,这样效率比较高.下面就介绍一种。

AChartEngine(简称ACE)是Google的一个开源图表库(for Android)。它功能强大,支持散点图、折线图、饼图、气泡图、柱状图、短棒图、仪表图等多种图表。

参考文章:http://www.cnblogs.com/android100/p/Android-AChartEngine.html

achartengine的数据模型

  • XYSeries: 最常用的数据结构,主要包括一系列的double型(x,y)点对及一个名称(title)。

  • XYValueSeries:包括一系列的(x,y,value)点对及一个名称(title)。

  • XYMultipleSeriesDataset:包含一系列XYSeries,是最终的数据结构

  • TimeSeries:与XYSeries类似,x变为Date型,可以转化为XYSeries。

  • CategorySeries:与XYSeries类似,x变为string型,可以转化为XYSeries。

  • MultipleCategorySeries:一系列CategorySeries。

不同的数据模型用于不同的图表显示。XYSeries可以用于折线图、直方图。CategorySeries可以用于圆饼图。每种数据模型都提供了丰富的操作接口,用于插入删除数据等多种操作。我们可以根据需要将数据存为合适的数据模型。

绘制器(渲染器Renderer)

绘制器声明了绘制图表的类型。主要包括以下几种。

SimpleSeriesRenderer、 XYSeriesRenderer用于设置每张图中每一个序列的绘制方法。而DefaultRenderer和 XYMultipleSeriesRenderer用于设置整张图的绘制格式。它们之间的关系类似于XYSeries 与XYMultipleSeriesDataset之间的关系。

画图概念

要 画一张图,我们需要设置好需要绘制的数据及绘制的方法。确定好data model及renderer后,再调用合适的绘制方法绘制图形。库提供了两种绘制图形的方法,一种是getIntent( )(如getLineChartIntent())直接新建一个Activity全屏显示生成的图表,另一种是getView( )(如getLineChartView())生成一个View,用户可以自行设置它的显示。

主要通过设置几个对象

1、XYSeries对象:用于存储一条线的数据信息;
2、XYMultipleSeriesDataset对象:即数据集,可添加多个XYSeries对象,因为一个折线图中可能有多条线。
3、XYSeriesRenderer对象:主要是用来设置一条线条的风格,颜色啊,粗细之类的。
4、XYMultipleSeriesRenderer对象:主要用来定义一个图的整体风格,设置xTitle,yTitle,chartName等等整体性的风格,
可添加多个XYSeriesRenderer对象,因为一个图中可以有多条折线。
设置完那些对象之后,可通过 org.achartengine.ChartFactory调用数据集XYMultipleSeriesDataset对象
与XYMultipleSeriesRenderer对象来画图并将图加载到GraphicalView中,
ChartFactory有多种api,通过这些api调用来决定是画折线图还是柱状图。

绘制基础

1,ChartFactory ,传入XYMutilpleSeriesRenderer,XYMutilpleSeriesDataset,然后,我们只需用 getXXXChartIntent(Context context,XYMutilpleSeriesRenderer,XYMutilpleSeriesDataset,)方法就可以进行图表的显示

2,XYMutilpleSeriesRenderer 用于进行绘制的设置,添加的XYSeriesRender对象,用于定义绘制的点集合设置,注意数量要和XYMutilpleSeriesDataset,添加的XYseries一致!!!

3,XYMutilpleSeriesDataset 用于数据的存放,添加的XYseries对象,用于提供绘制的点集合的数据

绘制实例

这个实例告诉我们,不必跟着AChartEngine也可以照样实现。只需要懂得原理就行。
原理就是

  • 1.构造渲染图
  • 2.进行显示(构建数据)
  • 3.对点的绘制进行设置
  • / 3.1设置颜色

    3.2设置点的样式

    3.3, 将要绘制的点添加到坐标绘制中

    3.4,重复 1~3的步骤绘制第二个系列点

package com.zsz.develop.mychart;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;

import org.achartengine.ChartFactory;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import java.util.Random;

/**
 * Created by shengzhong on 2015/7/29.
 */
public class ShowExamActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        // 1, 构造显示用渲染图
        XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
        // 2,进行显示
        XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
        // 2.1, 构建数据
        Random r = new Random();
        for (int i = 0; i < 2; i++) {
            XYSeries series = new XYSeries("test" + (i + 1));
            // 填充数据
            for (int k = 0; k < 10; k++) {
                // 填x,y值
                series.add(k, 20 + r.nextInt() % 100);
            }
            // 需要绘制的点放进dataset中
            dataset.addSeries(series);
        }
        // 3, 对点的绘制进行设置
        XYSeriesRenderer xyRenderer = new XYSeriesRenderer();
        // 3.1设置颜色
        xyRenderer.setColor(Color.BLUE);
        // 3.2设置点的样式
        xyRenderer.setPointStyle(PointStyle.SQUARE);
        // 3.3, 将要绘制的点添加到坐标绘制中
        renderer.addSeriesRenderer(xyRenderer);
        // 3.4,重复 1~3的步骤绘制第二个系列点
        xyRenderer = new XYSeriesRenderer();
        xyRenderer.setColor(Color.RED);
        xyRenderer.setPointStyle(PointStyle.CIRCLE);
        renderer.addSeriesRenderer(xyRenderer);
        // Intent intent = new LinChart().execute(this);
        Intent intent = ChartFactory
                .getLineChartIntent(this, dataset, renderer);
        startActivity(intent);



//          GraphicalView graphicalView = ChartFactory.getLineChartView(this, dataset, renderer);
//    llChart= (LinearLayout) findViewById(R.id.llChart);
  //  llChart.addView(graphicalView);
    }

}    

把得到的图标设置成View

绑定layout后找到LinearLayout,把他添加到LinearLayout里去

  GraphicalView graphicalView = ChartFactory.getLineChartView(this, dataset, renderer);
llChart= (LinearLayout) findViewById(R.id.llChart);
llChart.addView(graphicalView);

构建一个柱状图实例

先定义一个接口AChartAbstract

package com.zsz.develop.chartdemo;

import android.content.Context;
import android.content.Intent;

public interface AChartAbstract {
/**
 * 获取一个当前类型图标的Intent实例
 */
public Intent getIntent(Context context);
}

新建一个java类BarChart来实现AChartAbstract接口

package com.zsz.develop.chartdemo;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint;

import org.achartengine.ChartFactory;
import org.achartengine.model.CategorySeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.chart.BarChart.Type;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;

/**
 * Created by shengzhong on 2015/7/29.
 */
public class BarChart implements AChartAbstract {

public Intent getIntent(Context context) {
    Intent mIntent=ChartFactory.getBarChartIntent(context, getDataSet(), getRenderer(), Type.STACKED, "当月开票金额树状图");
    return mIntent;
}

/**
 * 构造数据
 * @return
 */
public XYMultipleSeriesDataset getDataSet() {
    // 构造数据
    XYMultipleSeriesDataset barDataset = new XYMultipleSeriesDataset();
    CategorySeries barSeries = new CategorySeries("2014年3月");
    barSeries.add(865.5969);
    barSeries.add(2492.6479);
    barSeries.add(891.0137);
    barSeries.add(0.0);
    barSeries.add(691.0568);
    barDataset.addSeries(barSeries.toXYSeries());
    return barDataset;
}

/**
 * 构造渲染器
 * @return
 */
public XYMultipleSeriesRenderer getRenderer() {
    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
//      renderer.setChartTitle("当月开票");
//      // 设置标题的字体大小
//      renderer.setChartTitleTextSize(16);
    renderer.setXTitle("事业部");
    renderer.setYTitle("单位(万元)");
    renderer.setAxesColor(Color.WHITE);
    renderer.setLabelsColor(Color.WHITE);
    // 设置X轴的最小数字和最大数字
    renderer.setXAxisMin(0.5);
    renderer.setXAxisMax(5.5);
    // 设置Y轴的最小数字和最大数字
    renderer.setYAxisMin(0);
    renderer.setYAxisMax(3000);
    renderer.addXTextLabel(1, "电网");
    renderer.addXTextLabel(2, "通信");
    renderer.addXTextLabel(3, "宽带");
    renderer.addXTextLabel(4, "专网");
    renderer.addXTextLabel(5, "轨交");
    renderer.setZoomButtonsVisible(true);
    // 设置渲染器允许放大缩小
    renderer.setZoomEnabled(true);
    // 消除锯齿
    renderer.setAntialiasing(true);
    // 设置背景颜色
    renderer.setApplyBackgroundColor(true);
    renderer.setBackgroundColor(Color.GRAY);
    // 设置每条柱子的颜色
    SimpleSeriesRenderer sr = new SimpleSeriesRenderer();
    sr.setColor(Color.YELLOW);
    renderer.addSeriesRenderer(sr);
    // 设置每个柱子上是否显示数值
    renderer.getSeriesRendererAt(0).setDisplayChartValues(true);
    // X轴的近似坐标数  (这样不显示横坐标)
    renderer.setXLabels(0);
    // Y轴的近似坐标数
    renderer.setYLabels(6);
    // 刻度线与X轴坐标文字左侧对齐
    renderer.setXLabelsAlign(Paint.Align.LEFT);
    // Y轴与Y轴坐标文字左对齐
    renderer.setYLabelsAlign(Paint.Align.LEFT);
    // 允许左右拖动,但不允许上下拖动.
    renderer.setPanEnabled(true, false);
    // 柱子间宽度
    renderer.setBarSpacing(0.5f);
    // 设置X,Y轴单位的字体大小
    renderer.setAxisTitleTextSize(20);
    return renderer;
}
}

主函数中调用

Intent lineIntent = new BarChart().getIntent(this);
    startActivity(lineIntent);

最后不要忘了在Androidmanifest.xml文件中进行配置文件

<activity android:name="org.achartengine.GraphicalActivity" />

Android Studio的两个概念:Project 和 Module

Android Studio中的两个概念。 Project 和 Module 。
在Android Studio中, Project 的真实含义是工作空间, Module 为一个具体的项目。

在 Eclipse 中,我们可以同时对多个 Eclipse 的 Project 进行同时编辑,这些 Project 在同一个 workspace 之中。在Android Studio中,我们可以同时对多个Android Studio的 Module 进行同时编辑,这些 Module 在同一个 Project 之中。

Eclipse 的 Project 等同于Android Studio的 Module 。
Eclipse 的 workspace 等同于Android Studio的 Project 。


AChartEngine日期折线图的例子

首先要导入他给的实例代码类AbstractDemoChart抽象类,和接口IDemoChart,与WeightDialChart

package com.zsz.develop.mychart;

import java.util.Date;
import java.util.List;

import org.achartengine.chart.PointStyle;
import org.achartengine.model.CategorySeries;
import org.achartengine.model.MultipleCategorySeries;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

public abstract class AbstractDemoChart implements IDemoChart {

/**
 * 构建 XYMultipleSeriesDataset.
 *
 * @param titles 每个序列的图例
 * @param xValues X轴的坐标
 * @param yValues Y轴的坐标
 * @return XYMultipleSeriesDataset
 */
protected XYMultipleSeriesDataset buildDataset(String[] titles, List<double[]> xValues,
                                               List<double[]> yValues) {
    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    addXYSeries(dataset, titles, xValues, yValues, 0);
    return dataset;
}

//向DataSet中添加序列.
public void addXYSeries(XYMultipleSeriesDataset dataset, String[] titles, List<double[]> xValues,
                        List<double[]> yValues, int scale) {
    int length = titles.length;
    for (int i = 0; i < length; i++) {
        XYSeries series = new XYSeries(titles[i], scale); //这里注意与TimeSeries区别.
        double[] xV = xValues.get(i);
        double[] yV = yValues.get(i);
        int seriesLength = xV.length;
        for (int k = 0; k < seriesLength; k++) {
            series.add(xV[k], yV[k]);
        }
        dataset.addSeries(series);
    }
}

/**
 * 构建XYMultipleSeriesRenderer.
 *
 * @param colors 每个序列的颜色
 * @param styles 每个序列点的类型(可设置三角,圆点,菱形,方块等多种)
 * @return XYMultipleSeriesRenderer
 */
protected XYMultipleSeriesRenderer buildRenderer(int[] colors, PointStyle[] styles) {
    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
    setRenderer(renderer, colors, styles);
    return renderer;
}

protected void setRenderer(XYMultipleSeriesRenderer renderer, int[] colors, PointStyle[] styles) {
    //整个图表属性设置
    //-->start
    renderer.setAxisTitleTextSize(16);//设置轴标题文字的大小
    renderer.setChartTitleTextSize(40);//设置整个图表标题文字的大小
    renderer.setLabelsTextSize(15);//设置轴刻度文字的大小
    renderer.setLegendTextSize(15);//设置图例文字大小
    renderer.setPointSize(5f);//设置点的大小(图上显示的点的大小和图例中点的大小都会被设置)
    renderer.setMargins(new int[] { 20, 30, 15, 20 });//设置图表的外边框(上/左/下/右)
    //-->end

    //以下代码设置没个序列的颜色.
    //-->start
    int length = colors.length;
    for (int i = 0; i < length; i++) {
        XYSeriesRenderer r = new XYSeriesRenderer();
        r.setColor(colors[i]);//设置颜色
        r.setPointStyle(styles[i]);
        renderer.addSeriesRenderer(r);
    }
    //-->end
}

/**
 * 设置renderer的一些属性.
 *
 * @param renderer 要设置的renderer
 * @param title 图表标题
 * @param xTitle X轴标题
 * @param yTitle Y轴标题
 * @param xMin X轴最小值
 * @param xMax X轴最大值
 * @param yMin Y轴最小值
 * @param yMax Y轴最大值
 * @param axesColor X轴颜色
 * @param labelsColor Y轴颜色
 */
protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,
                                String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor,
                                int labelsColor) {
    renderer.setChartTitle(title);
    renderer.setXTitle(xTitle);
    renderer.setYTitle(yTitle);
    renderer.setXAxisMin(xMin);
    renderer.setXAxisMax(xMax);
    renderer.setYAxisMin(yMin);
    renderer.setYAxisMax(yMax);
    renderer.setAxesColor(axesColor);
    renderer.setLabelsColor(labelsColor);
}

/**
 * 构建和时间有关的XYMultipleSeriesDataset,这个方法与buildDataset在参数上区别是需要List<Date[]>作参数.
 *
 * @param titles 序列图例
 * @param xValues X轴值
 * @param yValues Y轴值
 * @return XYMultipleSeriesDataset
 */
protected XYMultipleSeriesDataset buildDateDataset(String[] titles, List<Date[]> xValues,
                                                   List<double[]> yValues) {
    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    int length = titles.length;
    for (int i = 0; i < length; i++) {
        TimeSeries series = new TimeSeries(titles[i]);//构建时间序列TimeSeries,
        Date[] xV = xValues.get(i);
        double[] yV = yValues.get(i);
        int seriesLength = xV.length;
        for (int k = 0; k < seriesLength; k++) {
            series.add(xV[k], yV[k]);
        }
        dataset.addSeries(series);
    }
    return dataset;
}

/**
 * 构建单个CategorySeries,可用于生成饼图,注意与buildMultipleCategoryDataset(构建圆环图)相区别.
 *
 * @param titles the series titles
 * @param values the values
 * @return the category series
 */
protected CategorySeries buildCategoryDataset(String title, double[] values) {
    CategorySeries series = new CategorySeries(title);
    int k = 0;
    for (double value : values) {
        series.add("Project " + ++k, value);
    }

    return series;
}

/**
 * 构建MultipleCategorySeries,可用于构建圆环图(每个环是一个序列)
 *
 * @param titles the series titles
 * @param values the values
 * @return the category series
 */
protected MultipleCategorySeries buildMultipleCategoryDataset(String title,
                                                              List<String[]> titles, List<double[]> values) {
    MultipleCategorySeries series = new MultipleCategorySeries(title);
    int k = 0;
    for (double[] value : values) {
        series.add(2007 + k + "", titles.get(k), value);
        k++;
    }
    return series;
}

/**
 * 构建DefaultRenderer.
 *
 * @param colors 每个序列的颜色
 * @return DefaultRenderer
 */
protected DefaultRenderer buildCategoryRenderer(int[] colors) {
    DefaultRenderer renderer = new DefaultRenderer();
    renderer.setLabelsTextSize(15);
    renderer.setLegendTextSize(15);
    renderer.setMargins(new int[] { 20, 30, 15, 0 });
    for (int color : colors) {
        SimpleSeriesRenderer r = new SimpleSeriesRenderer();
        r.setColor(color);
        renderer.addSeriesRenderer(r);
    }
    return renderer;
}

/**
 * 构建XYMultipleSeriesDataset,适用于柱状图.
 *
 * @param titles 每中柱子序列的图列
 * @param values 柱子的高度值
 * @return XYMultipleSeriesDataset
 */
protected XYMultipleSeriesDataset buildBarDataset(String[] titles, List<double[]> values) {
    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    int length = titles.length;
    for (int i = 0; i < length; i++) {
        CategorySeries series = new CategorySeries(titles[i]);
        double[] v = values.get(i);
        int seriesLength = v.length;
        for (int k = 0; k < seriesLength; k++) {
            series.add(v[k]);
        }
        dataset.addSeries(series.toXYSeries());
    }
    return dataset;
}

/**
 * 构建XYMultipleSeriesRenderer,适用于柱状图.
 *
 * @param colors 每个序列的颜色
 * @return XYMultipleSeriesRenderer
 */
protected XYMultipleSeriesRenderer buildBarRenderer(int[] colors) {
    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
    renderer.setAxisTitleTextSize(16);
    renderer.setChartTitleTextSize(20);
    renderer.setLabelsTextSize(15);
    renderer.setLegendTextSize(15);
    int length = colors.length;
    for (int i = 0; i < length; i++) {
        SimpleSeriesRenderer r = new SimpleSeriesRenderer();
        r.setColor(colors[i]);
        renderer.addSeriesRenderer(r);
    }
    return renderer;
}

}

=======
接口IDemoChart

/**
 * Copyright (C) 2009 - 2013 SC 4ViewSoft SRL
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zsz.develop.mychart;

import android.content.Context;
import android.content.Intent;

/**
 * Defines the demo charts.
 */
public interface IDemoChart {
  /** A constant for the name field in a list activity. */
  String NAME = "name";
  /** A constant for the description field in a list activity. */
  String DESC = "desc";

  /**
   * Returns the chart name.
   * 
   * @return the chart name
   */
  String getName();

  /**
   * Returns the chart description.
   * 
   * @return the chart description
   */
  String getDesc();

  /**
   * Executes the chart demo.
   * 
   * @param context the context
   * @return the built intent
   */
  Intent execute(Context context);

}

======
/**

 * Copyright (C) 2009 - 2013 SC 4ViewSoft SRL
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.zsz.develop.mychart;

import org.achartengine.ChartFactory;
import org.achartengine.model.CategorySeries;
import org.achartengine.renderer.DialRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.DialRenderer.Type;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;

/**
 * Budget demo pie chart.
 */
public class WeightDialChart extends AbstractDemoChart {
  /**
   * Returns the chart name.
   * @return the chart name
   */
  public String getName() {
    return "Weight chart";
  }

  /**
   * Returns the chart description.
   * @return the chart description
   */
  public String getDesc() {
    return "The weight indicator (dial chart)";
  }

  /**
   * Executes the chart demo.
   * @param context the context
   * @return the built intent
   */
  public Intent execute(Context context) {
   CategorySeries category = new CategorySeries("Weight indic");
category.add("Current", 75);
category.add("Minimum", 65);
category.add("Maximum", 90);
DialRenderer renderer = new DialRenderer();
renderer.setChartTitleTextSize(20);
renderer.setLabelsTextSize(15);
renderer.setLegendTextSize(15);
renderer.setMargins(new int[] {20, 30, 15, 0});
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(Color.BLUE);
renderer.addSeriesRenderer(r);
r = new SimpleSeriesRenderer();
r.setColor(Color.rgb(0, 150, 0));
renderer.addSeriesRenderer(r);
r = new SimpleSeriesRenderer();
r.setColor(Color.GREEN);
renderer.addSeriesRenderer(r);
renderer.setLabelsTextSize(10);
renderer.setLabelsColor(Color.WHITE);
renderer.setShowLabels(true);
renderer.setVisualTypes(new Type[] {Type.ARROW, Type.NEEDLE, Type.NEEDLE});
renderer.setMinValue(0);
renderer.setMaxValue(150);
return ChartFactory.getDialChartIntent(context, category, renderer, "Weight indicator");
  }

}

通过这个WeightTimeChart类进行实现

/**
 * WeightTimeChart.java
 * 版权所有(C) 2013 
 * 创建:cuiran 2013-10-24 下午4:11:28
 */
package com.zsz.develop.mychart;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import org.achartengine.ChartFactory;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.TimeChart;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;



import android.content.Context;
import android.content.Intent;
import android.graphics.Color;

/**
 * TODO 折线图
 * @author cuiran
 * @version 1.0.0
 */
public class WeightTimeChart extends AbstractDemoChart {
private static final int SERIES_NR = 1;
/* (non-Javadoc)
 * @see com.cayden.weightnotes.achartengine.IDemoChart#getName()
 */
@Override
public String getName() {
    // TODO Auto-generated method stub
    return "WeightTimeChart";
}

public static Date strToDate(String strDate) {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    ParsePosition pos = new ParsePosition(0);
    Date strtodate = formatter.parse(strDate, pos);
    return strtodate;
}

/* (non-Javadoc)
 * @see com.cayden.weightnotes.achartengine.IDemoChart#getDesc()
 */
@Override
public String getDesc() {
    // TODO Auto-generated method stub
    return "WeightTimeChart";
}

private XYMultipleSeriesDataset getDateDemoDataset() {
    XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
    final int nr = 7;



    long value = new Date().getTime() - 3 * TimeChart.DAY;
    Random r = new Random();
    for (int i = 0; i < SERIES_NR; i++) {
        TimeSeries series = new TimeSeries("体重变化趋势 ");

        series.add(WeightTimeChart.strToDate("2013-10-19"), 85.3);
        series.add(WeightTimeChart.strToDate("2013-10-20"), 85.6);
        series.add(WeightTimeChart.strToDate("2013-10-21"), 84.5);
        series.add(WeightTimeChart.strToDate("2013-10-22"), 85.0);
        series.add(WeightTimeChart.strToDate("2013-10-23"), 85.1);
        series.add(WeightTimeChart.strToDate("2013-10-24"), 85.3);
        series.add(WeightTimeChart.strToDate("2013-10-25"), 85.3);
        series.add(WeightTimeChart.strToDate("2013-10-26"), 85.3);

//              for (int k = 0; k < nr; k++) {
//                series.add(new Date(value + k * TimeChart.DAY / 4), 20 + r.nextInt() % 100);
//              }

        dataset.addSeries(series);

    }
    return dataset;
}

private XYMultipleSeriesRenderer getDemoRenderer() {
    XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
    renderer.setAxisTitleTextSize(40);
    renderer.setChartTitleTextSize(40);
    renderer.setLabelsTextSize(40);
    renderer.setLegendTextSize(18);
    renderer.setPointSize(6f);
    //in this order: top, left, bottom, right
    renderer.setMargins(new int[] {20, 30, 15, 0});


    XYSeriesRenderer r = new XYSeriesRenderer();

    r = new XYSeriesRenderer();
    r.setPointStyle(PointStyle.CIRCLE);
    r.setColor(Color.GREEN);
    r.setFillPoints(true);

    renderer.addSeriesRenderer(r);
    renderer.setAxesColor(Color.DKGRAY);
    renderer.setLabelsColor(Color.LTGRAY);
    renderer.setChartTitle("体重变化趋势");
    renderer.setXTitle("日期");
    renderer.setYTitle("体重(kg)");
    renderer.setZoomButtonsVisible(true);

    int length = renderer.getSeriesRendererCount();
    for (int i = 0; i < length; i++) {
        SimpleSeriesRenderer seriesRenderer = renderer.getSeriesRendererAt(i);
        seriesRenderer.setDisplayChartValues(true);
    }
    return renderer;
}
/* (non-Javadoc)
 * @see com.cayden.weightnotes.achartengine.IDemoChart#execute(android.content.Context)
 */
@Override
public Intent execute(Context context) {
    // TODO Auto-generated method stub

    return ChartFactory.getTimeChartIntent(context, getDateDemoDataset(), getDemoRenderer(), "yyyy-MM-dd");
}

}

最后在MainActivity里调用

package com.zsz.develop.mychart;

import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;


public class MainActivity extends ActionBarActivity {

private IDemoChart[] mCharts = new IDemoChart[] {new WeightDialChart(),
        new WeightTimeChart()};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent=mCharts[1].execute(this);

    startActivity(intent);

}



}

最后别忘了在配置文件中添加

json转化异常,JDBC查询之感悟

2015/7/28问题集

json转化异常

异常信息为:Expected BEGIN_ARRAY but was BEGIN_OBJECT
说不是数组,查找到当时的json数据.

{“id”:0,”name”:”zsz”,”age”:22,”goalTime”:”2015/7/28”,”goalWeight”:0.0,”height”:2.0}
这并不是一条数组信息

不管你有几条数据:他都要是一个数组类型。也就是返回的是一个list集合。

[{“id”:0,”name”:”zsz”,”age”:22,”goalTime”:”2015/7/28”,”goalWeight”:0.0,”height”:2.0}]

修改方法 ###添加的时候、不要在for循环里添加。

listDataBeans=dataDao.getEditData(jsonNameStr);
            for (int i = 0; i < listDataBeans.size(); i++) {
               DataBean dataBean=listDataBeans.get(i);
               System.out.println(dataBean.getGoalTime()+"傻逼");
           }
            dataString = gson.toJson(listDataBeans);

JDBC查询之感悟

查询必定是通过一个条件来查找,返回的数据可能会有多条(List)。
查询出来是一个ResultSet,所以也需要一条一条读取出来。有值得时候就设置进属性。

    public ArrayList<ManBean> getAllMan(String name) {

    boolean b=false;
    ArrayList<ManBean> arrayList=new ArrayList<ManBean>();
    Connection conn=null;
    PreparedStatement ps=null;
    ResultSet rs=null;
    String getAllManSQL="SELECT * FROM man "+"WHERE name=?";
    try {
        conn=BaseConnection.getConnection();
        ps=(PreparedStatement) conn.prepareStatement(getAllManSQL);
        ps.setString(1, name);
        System.out.println(ps+")))))"+name);
        rs=ps.executeQuery();
        String line;
        StringBuffer sb=new StringBuffer();
        while (rs.next()) {
            ManBean manBean=new ManBean();
            manBean.setArm(rs.getString("arm"));
            manBean.setChest(rs.getString("chest"));
            manBean.setImage(rs.getBytes("image"));
            manBean.setTime(rs.getString("time"));
            manBean.setName(rs.getString("name"));
            manBean.setWeight(rs.getString("weight"));
            manBean.setWaust(rs.getString("waust"));
            manBean.setId(rs.getInt("id"));
            arrayList.add(manBean);
        }
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }finally {
        BaseConnection.closeResource(rs, ps, conn);
    }

    return arrayList;
}

JDBC等一干操作

@Override
public boolean deleteMan(int id) {

    boolean b=false;
    Connection conn=null;
    PreparedStatement ps=null;
    String deleteManSQL="DELETE FROM man WHERE id=?";
    try {
        conn=BaseConnection.getConnection();
        ps=(PreparedStatement) conn.prepareStatement(deleteManSQL);
        ps.setInt(1, id);
        System.out.println(deleteManSQL);
        int i=ps.executeUpdate();
        if (i>0) {
            b=true;
        }


    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        BaseConnection.closeResource(ps, conn);
    }

    return b;
}

控件对齐方式

控件对齐方式

<?xml version=”1.0” encoding=”utf-8”?>
<!—

  • android:layout_above 将该控件的底部至于给定ID的控件之上

  • android:layout_below 将该控件的顶部至于给定ID的控件之下

  • android:layout_toLeftOf 将该控件的右边缘和给定ID的控件的左边缘对齐
  • android:layout_toRightOf 将该控件的左边缘和给定ID的控件的右边缘对齐

  • android:layout_alignBaseline 该控件的baseline和给定ID的控件的baseline对齐

  • android:layout_alignBottom 将该控件的底部边缘与给定ID控件的底部边缘
  • android:layout_alignLeft 将该控件的左边缘与给定ID控件的左边缘对齐
  • android:layout_alignRight 将该控件的右边缘与给定ID控件的右边缘对齐
  • android:layout_alignTop 将给定控件的顶部边缘与给定ID控件的顶部对齐
  • android:alignParentBottom 如果该值为true,则将该控件的底部和父控件的底部对齐
  • android:layout_alignParentLeft 如果该值为true,则将该控件的左边与父控件的左边对齐
  • android:layout_alignParentRight 如果该值为true,则将该控件的右边与父控件的右边对齐
  • android:layout_alignParentTop 如果该值为true,则将空间的顶部与父控件的顶部对齐

  • android:layout_centerHorizontal 如果值为真,该控件将被至于水平方向的中央

  • android:layout_centerInParent 如果值为真,该控件将被至于父控件水平方向和垂直方向的中央
  • android:layout_centerVertical 如果值为真,该控件将被至于垂直方向的中央
  • android:padding和android:layout_margin 通俗的理解 Padding 为内边框,Margin 为外边框
  • android:padding和android:layout_margin的区别,其实概念很简单,padding是站在父view的角度描述问题,它规定它里面的内容必须与这个父view边界的距离。margin则是站在自己的角度描述问题,规定自己和其他(上下左右)的view之间的距离,如果同一级只有一个view,那么它的效果基本上就和padding一样了。

  • android:layout_gravity=”center”

  • android:gravity 属性是对该view 内容的限定.比如一个button 上面的text. 你可以设置该text 在view的靠左,靠右等位置..
  • android:layout_gravity是用来设置该view相对与起父view 的位置.比如一个button 在linearlayout里,你想把该button放在靠左  靠右等位置就可以通过该属性设置.