
Android用のグラフのライブラリーもあるみたいですけど、いまいちなのでオリジナルな棒グラフを作成してみます。プログラミングの大した技量が僕には無いので至ってシンプルな棒グラフです。ちなみに、オリジナルな棒グラフは配布中のカウンターアプリにも乗せているので、試してみてください(営業)。
カスタムビューの作成
クラス名は何でも良いんですけど、棒グラフだし、僕のイニシャルはHSなので、HsGraphBarというクラスを作成します。extendsするのは、Viewでもイイ気がするんですが、なんとなくLinearLayoutを拡張します。package jp.blogcms.livedoor.hsgraph;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.LinearLayout;
public class HsGraphBar extends LinearLayout{
/**
* コンストラクター
* Viewのクラス内では、getContext()でcontextの取得ができる
*
* @param context
*/
public HsGraphBar(Context context) {
super(context);
}
/**
* AddViewなんかで実際にviewが追加されたときに呼び出される
*
*/
@Override
protected void onAttachedToWindow(){
super.onAttachedToWindow();
}
/**
* タテヨコの大きさを決める時に呼び出される
* Viewの大きさを指定したい場合は、ここで指定
*
*/
@Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
}
/**
* レイアウトを決める時に呼び出される
*
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
/**
* 描画する!
*
*/
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}Viewのきっと使うであろうイベントです。この上の並んだ順番で、それぞれのメソッドはViewを作成するときに必ず呼び出されます。グラフ作成で大事なのは、onMeasureとonDarawかと思います。使わないイベントは消しちゃって構いません。まぁ、正直なところandroidのViewの生成のされ方に関して、僕も大して理解してません・・・。察しの通り、上記はイベントを書いただけなんで、内容は無いよう・・・。グラフの大きさを指定する
まずは、グラフの大きさを決めたいと思います。サイズ決めって凡化を考えると凄く面倒なので、ここでは、View内でグラフの大きさを指定してしまいます!高さは、300dpくらいがイイなとじっちゃんが言ってたので300とします。幅は、親のLinearLayoutの幅をそのまま使うようにします。xmlで書くときのmatch_parent(fill_parent)です。
まず、HsGraphBarクラス内に高さを持たせたフィールドを宣言します。じっちゃんが300って言ってたので300。
int graphHeight = 300;
で、幅と合わせて大きさをonMeasuredイベント内で宣言します
@Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
//グラフのサイズを指定
setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, graphHeight));
}解りにくいんですけど、このHsGraphBarがLinearLayoutを拡張しているからLinearLayout.LayoutParamsを使っているのでは無くて、親の要素がLinearLayoutだからLinearLayout.LayoutParamsです。つまるところ、HsGraphBarは、LinearLayoutの下でしか生きていけません。これ、たぶん、駄目な書き方です。はい。 本当は、クラスの外から指定してやるのが正解なんだろーけど、まぁ、いいんじゃないのかっていう。これで、グラフの大きさが指定できました!ひゃっほーい!グラフにするデータを用意する
必要なデータは、- グラフ一本一本の値
- x軸のラベル
で、グラフの値とx軸のラベルは、それぞれリンクしているとします。Javaをよく知らないし、そもそもプログラミングがよくわかってないので、そのまんま配列を使ってデータを扱いたい。そう僕は思います。そんな訳でHsGraph内にフィールドを作成します
ついでにHsGraph内にセッターも作成します
//グラフの値 List<Integer>values = new ArrayList<Integer>(); //グラフのxラベル List<String>xLabels = new ArrayList<String>();valuesとxLabelsは、別個のフィールドなんですけど、それぞれのインデックスは同じものを指してるようにします(してください)。LinkedListがいいんだぜ(キリッ って記事を見かけるんですけど、LinkedListがイイ人は使えばいいのかと。
ついでにHsGraph内にセッターも作成します
/**
* 棒グラフの値を一度にセットする
*
*
*/
public void setValues(List<Integer>values){
this.values = values;
}
/**
* x軸のラベルを一度に全部セットする
*
*
*/
public void setXLabels(List<String>xLabels){
this.xLabels = xLabels;
} ここまでのコードのまとめ
サクッと書いてサクッと寝るつもりだったんですけど、予想外に長くなってきたのでここまでのコードの全部を載せたいと思います。完成してません。package jp.blogcms.livedoor.hsgraph;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.LinearLayout;
public class HsGraphBar extends LinearLayout{
//グラフの高さ
int graphHeight = 300;
//グラフの値
List<Integer>values = new ArrayList<Integer>();
//グラフのxラベル
List<String>xLabels = new ArrayList<String>();
/**
* コンストラクター
* Viewのクラス内では、getContext()でcontextの取得ができる
*
* @param context
*/
public HsGraphBar(Context context) {
super(context);
}
/**
* 棒グラフの値を一度にセットする
*
*
*/
public void setValues(List<Integer>values){
this.values = values;
}
/**
* x軸のラベルを一度に全部セットする
*
*
*/
public void setXLabels(List<String>xLabels){
this.xLabels = xLabels;
}
/**
* AddViewなんかで実際にviewが追加されたときに呼び出される
*
*/
@Override
protected void onAttachedToWindow(){
super.onAttachedToWindow();
}
/**
* タテヨコの大きさを決める時に呼び出される
* Viewの大きさを指定したい場合は、ここで指定
*
*/
@Override
protected void onMeasure(int width, int height) {
super.onMeasure(width, height);
//グラフのサイズを指定
setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, graphHeight));
}
/**
* レイアウトを決める時に呼び出される
*
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
/**
* 描画する!
*
*/
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}カスタムビューをプログラム上で追加
ちなみに、HsGraphBarをプログラム上で実際のレイアウトに追加する方法は、こんな感じです。Activity内やFragment内から呼び出してください。 //グラフビューを作成
HsGraphBar graph = new HsGraphBar(this);
//グラフの値
List<Integer>values = new ArrayList<Integer>();
//グラフのxラベル
List<String>xLabels = new ArrayList<String>();
//偽のデータを用意します
Random rnd = new Random();
for(int i=0;i<5;i++){
values.add(rnd.nextInt(100));
xLabels.add(String.valueOf(i) + "番目");
}
//値をグラフに渡す
graph.setValues(values);
//xラベルをグラフに渡す
graph.setXLabels(xLabels);
//グラフを挿入
//追加できるのはLinearLayoutのみ!
((LinearLayout)findViewById(R.id.graphTarget)).addView(graph);グラフをcanvasを使って描画する前に下準備
前置きが長くなりました。描画したいと思うのですが、一個だけ。デフォルトだとonDrawが呼び出されないので、呼び出すように設定します。 public HsGraphBar(Context context) {
super(context);
setWillNotDraw(false);
}setWillNotDraw()に引数falseを渡しておきます。こうすることでonDrawが呼び出されます。
グラフをcanvasを使って描画する前に、データの整理
最大値を探し出すグラフの棒の高さは、valuesそれぞれの値に基づいてきまります。で、最大値がグラフの高さとなるので、とりあえず、のちのち便利な最大値を保持するフィールドを宣言します。
//valuesの中の最大値 Integer maxValue = 0;valuesの最大値を探し出します。
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//valuesの中の最大値を見つけ出す
for(int i=0;i<values.size();i++){
if(values.get(i)>maxValue){
maxValue = values.get(i);
}
}
}どのタイミングで探し出すのがベストなのかわかんないんですけど、ここではonDrawで呼び出してます。グラフのサイズを決定する
細かいんですけど、このHsGraphのサイズが棒グラフそのままのサイズになるわけではありません。実際に棒グラフを描くスペースは、ラベルのサイズを考慮してやる必要があります。イメージとしてはこんな感じ。

実際のグラフのサイズを計算していきます。
まずは、高さから計算していきましょう。計算したグラフの高さは、HsGraphクラス内にplotHeightフィールドを作成してそこで保持するようにします。
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//valuesの中の最大値を見つけ出す
for(int i=0;i<values.size();i++){
if(values.get(i)>maxValue){
maxValue = values.get(i);
}
}
//ラベルのペイントを取る
Paint txtPaint = getLabelPaint();
//高さを出したいので、仮に一番最初のラベルの文字列を取得します
String xLabel = xLabels.get(0);
//四角形
Rect bounds = new Rect();
//指定した文字列を入れる四角形を作成
txtPaint.getTextBounds(xLabel,0,xLabel.length(),bounds);
//四角形の高さを取得 = 文字列の高さ
int xHeight = bounds.height();
//グラフだけの高さを計算
plotHeight = getMeasuredHeight()-xHeight;
}
/**
* ラベルの色・サイズはY軸、X軸ともに共通のを使用するので一つにまとめます
* Paintは、色やサイズなんかを保持するオブジェクトです。
*
*
*/
private Paint getLabelPaint(){
Paint paint = new Paint();
//アンチエイリアス
paint.setAntiAlias(true);
//文字の色
paint.setColor(Color.parseColor("#777777"));
//文字のサイズ
paint.setTextSize(15);
return paint;
}次にY軸の幅を出して、グラフの幅を計算したいと思います。ただY軸ラベルの値はまだ計算してないので、ついでに計算してyLabelsとして配列の中にいれたいと思います。まずは、y軸の線の数を決めます。フィールドで宣言するだけ。ばっちゃんが5個くらい線があるといいよって言ってたので5個線を書こう。そう思います。
//ヨコの線の数を指定します。5個くらい線を描こうかと思います・・・。 Integer yLineCount = 5;
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//valuesの中の最大値を見つけ出す
for(int i=0;i<values.size();i++){
if(values.get(i)>maxValue){
maxValue = values.get(i);
}
}
//ラベルのペイントを取る
Paint txtPaint = getLabelPaint();
//高さを出したいので、仮に一番最初のラベルの文字列を取得します
String xLabel = xLabels.get(0);
//四角形
Rect bounds = new Rect();
//指定した文字列を入れる四角形を作成
txtPaint.getTextBounds(xLabel,0,xLabel.length(),bounds);
//四角形の高さを取得 = 文字列の高さ
int xHeight = bounds.height();
//グラフだけの高さを計算
plotHeight = getMeasuredHeight()-xHeight;
//### Y軸ラベルを作成 ###
//それぞれのYの値を計算。誤差を少なくする為に一旦floatに変えてます
Float eachY = maxValue.floatValue()/yLineCount.floatValue();
Float tmpY = 0F;
//先にフィールドとして宣言したyLabelsを初期化
yLabels = new ArrayList<String>();
for(int i=0; i<yLineCount; i++){
yLabels.add( String.valueOf(tmpY.intValue()));
tmpY = tmpY + eachY;
}
}xのラベルの高さをだしたようにyのラベルの幅を取得して、グラフの幅を計算します。
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//valuesの中の最大値を見つけ出す
for(int i=0;i<values.size();i++){
if(values.get(i)>maxValue){
maxValue = values.get(i);
}
}
//ラベルのペイントを取る
Paint txtPaint = getLabelPaint();
//高さを出したいので、仮に一番最初のラベルの文字列を取得します
String txt = xLabels.get(0);
//四角形
Rect bounds = new Rect();
//指定した文字列を入れる四角形を作成
txtPaint.getTextBounds(txt,0,txt.length(),bounds);
//四角形の高さを取得 = 文字列の高さ
int xHeight = bounds.height();
//グラフだけの高さを計算
plotHeight = getMeasuredHeight()-xHeight;
//### Y軸ラベルを作成 ###
//それぞれのYの値を計算。誤差を少なくする為に一旦floatに変えてます
Float eachY = maxValue.floatValue()/yLineCount.floatValue();
Float tmpY = 0F;
//先にフィールドとして宣言したyLabelsを初期化
yLabels = new ArrayList<String>();
for(int i=0; i<yLineCount; i++){
yLabels.add( String.valueOf(tmpY.intValue()));
tmpY = tmpY + eachY;
}
//y軸の幅を取得します。変数はxのを流用。
//一番最後の値がでかそうなので一番最後の文字列を取得
txt = yLabels.get(yLabels.size()-1);
txtPaint.getTextBounds(txt,0,txt.length(),bounds);
int yWidth = bounds.width();
//グラフだけの幅を計算
plotWidth = getMeasuredWidth() - yWidth;
}ちなみにgetMeasuredWidth()やgetMeasuredHeight()は、クラスの幅や高さを取るメソッドです。オリジナルなビューを作るときには良く使います。きっと。あと、書いてて思ったんですけど、この辺の計算は、onLayoutとかonMeasureなんかでした方がいいのかも・・・。onDrawでオブジェクトを作成すんなハゲってEclipseさんで電球マークが表示される・・・。
canvasを使ってグラフを描画する!
androidのdrawには、後から書いたものが上にでるの法則があるらしく、1.ラベル、2.グラフの背景、3.バー本体の順番に書いていきたいと思います。なにやらonDrawが長くなってきたので、それぞれメソッドにわけてみます。 public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//valuesの中の最大値を見つけ出す
for(int i=0;i<values.size();i++){
if(values.get(i)>maxValue){
maxValue = values.get(i);
}
}
//ラベルのペイントを取る
Paint txtPaint = getLabelPaint();
//高さを出したいので、仮に一番最初のラベルの文字列を取得します
String txt = xLabels.get(0);
//四角形
Rect bounds = new Rect();
//指定した文字列を入れる四角形を作成
txtPaint.getTextBounds(txt,0,txt.length(),bounds);
//四角形の高さを取得 = 文字列の高さ
int xHeight = bounds.height();
//グラフだけの高さを計算
plotHeight = getMeasuredHeight()-xHeight;
//### Y軸ラベルを作成 ###
//それぞれのYの値を計算。誤差を少なくする為に一旦floatに変えてます
Float eachY = maxValue.floatValue()/yLineCount.floatValue();
Float tmpY = 0F;
//先にフィールドとして宣言したyLabelsを初期化
yLabels = new ArrayList<String>();
for(int i=0; i<yLineCount; i++){
yLabels.add( String.valueOf(tmpY.intValue()));
tmpY = tmpY + eachY;
}
//y軸の幅を取得します。変数はxのを流用。
//一番最後の値がでかそうなので一番最後の文字列を取得
txt = yLabels.get(yLabels.size()-1);
txtPaint.getTextBounds(txt,0,txt.length(),bounds);
int yWidth = bounds.width();
//グラフだけの幅を計算
plotWidth = getMeasuredWidth() - yWidth;
//描画する!
drawLabels(canvas);
drawBackground(canvas);
drawBars(canvas);
}
/**
* ラベルの色・サイズはY軸、X軸ともに共通のを使用するので一つにまとめます
* Paintは、色やサイズなんかを保持するオブジェクトです。
*
*
*/
private Paint getLabelPaint(){
Paint paint = new Paint();
//アンチエイリアス
paint.setAntiAlias(true);
//文字の色
paint.setColor(Color.parseColor("#777777"));
//文字のサイズ
paint.setTextSize(15);
return paint;
}
/**
* ラベルを書く
*
* @param canvas
*/
private void drawLabels(Canvas canvas){
}
/**
* 背景を書く
*
* @param canvas
*/
private void drawBackground(Canvas canvas){
}
/**
* バーを書く
*
* @param canvas
*/
private void drawBars(Canvas canvas){
} X軸とy軸のラベルを書く
Yのラベルを書いていきます。
private void drawLabels(Canvas canvas){
Paint paint = getLabelPaint();
//## Yのラベルを描く!
//線のそれぞれの高さを計算
Float yEach = plotHeight.floatValue()/yLineCount.floatValue();
//yLabelsは、0から入ってるのでグラフの下の部分から描画します。
Float yCurrent = plotHeight.floatValue();
for(int i=0; i< yLabels.size();i++){
//テキストを描画します。
canvas.drawText(yLabels.get(i), 0, yCurrent, paint);
//次の位置を計算
yCurrent = yCurrent - yEach;
}
}例によって誤差が怖いのでfloatにしてるんですが、最初からfloatで保持しとけばいいんじゃね?って驚愕の事実に前から薄々気づいていたのは内緒です。canvas.drawText(yLabels.get(i), 0, yCurrent, paint);
- 第一引数に文字列
- 第二引数にxの位置
- 第三引数にyの位置
- 第三引数にPaintオブジェクト
Paint paint = getLabelPaint();
//右揃えにする
paint.setTextAlign(Align.RIGHT);
//## Yのラベルを描く!
//線のそれぞれの高さを計算
Float yEach = plotHeight.floatValue()/yLineCount.floatValue();
//yLabelsは、0から入ってるのでグラフの下の部分から描画します。
Float yCurrent = plotHeight.floatValue();
//前に計算した文字列の幅をもっかい計算するという愚行
int xPos = getMeasuredWidth() - plotWidth;
for(int i=0; i< yLabels.size();i++){
//テキストを描画します。
//xの位置は、右側を指定
canvas.drawText(yLabels.get(i), xPos, yCurrent, paint);
//次の位置を計算
yCurrent = yCurrent - yEach;
}この場合のxは、文字列の右側が開始位置となります。次、Xのラベル!Yと似たようなもんです!今度は、yの値を固定してxをずらしていきます!
//中央ぞろえ
paint.setTextAlign(Align.CENTER);
//それぞれの幅を計算
Float xEach = plotWidth.floatValue()/((Integer)xLabels.size()).floatValue();
//さらにそれぞれの真ん中の位置を計算
Float center = xEach/2;
//yで計算したxの位置を流用。
Float tmpX = xPlotStart + center;
for(int i=0;i<xLabels.size();i++){
canvas.drawText(xLabels.get(i), tmpX, getMeasuredHeight(), paint);
tmpX = tmpX + xEach;
}棒の幅なんですけど、ここでは、ビューの幅と棒の数から幅を割り出しています。ここの値は固定にしてもいいのかと。お好きなように・・・・。で、実行してみるとこんな感じ

/**
* ラベルを書く
*
* @param canvas
*/
private void drawLabels(Canvas canvas){
Paint paint = getLabelPaint();
//右揃えにする
paint.setTextAlign(Align.RIGHT);
//## Yのラベルを描く!
//線のそれぞれの高さを計算
Float yEach = plotHeight.floatValue()/yLineCount.floatValue();
//yLabelsは、0から入ってるのでグラフの下の部分から描画します。
Float yCurrent = plotHeight.floatValue();
//微調整。文字の大きさの半分だけずらす
Rect bounds = new Rect();
paint.getTextBounds(yLabels.get(0), 0, 1, bounds);
yCurrent = yCurrent + (bounds.height()/2);
//前に計算した文字列の幅をもっかい計算するという愚行
int xPlotStart = getMeasuredWidth() - plotWidth;
for(int i=0; i< yLabels.size();i++){
//テキストを描画します。
//xの位置は、右側を指定
canvas.drawText(yLabels.get(i), xPlotStart, yCurrent, paint);
//次の位置を計算
yCurrent = yCurrent - yEach;
}
//## Xのラベルを描く!
//中央ぞろえ
paint.setTextAlign(Align.CENTER);
//それぞれの幅を計算
Float xEach = plotWidth.floatValue()/((Integer)xLabels.size()).floatValue();
//さらにそれぞれの真ん中の位置を計算
Float center = xEach/2;
//yで計算したxの位置を流用。
Float tmpX = xPlotStart + center;
for(int i=0;i<xLabels.size();i++){
canvas.drawText(xLabels.get(i), tmpX, getMeasuredHeight(), paint);
tmpX = tmpX + xEach;
}
}背景を書く!
背景色!
ほんのりと背景色を付けます。
/**
* 背景を書く
*
* @param canvas
*/
private void drawBackground(Canvas canvas){
Paint paint = new Paint();
paint.setAntiAlias(true);
int plotStartX = getMeasuredWidth() - plotWidth;
int plotStartY = 0;
//background
paint.setColor(Color.parseColor("#EFEFEF"));
Rect rect = new Rect(plotStartX, 0, getMeasuredWidth(), plotHeight);
canvas.drawRect(rect, paint);
} drawRectは、四角形を描きます!引数がleft,top,right,bottomってなってるんですけど、それぞれの線の位置を思い浮かべれば解り易いのかと・・・。leftは四角形の左側の線。topは上の線。rightは右側で、bottomは下の線・・・・。線を引く!
//## yの線を描く!
paint.setColor(Color.parseColor("#999999"));
Float yEach = plotHeight.floatValue()/yLineCount.floatValue();
//yLabelsは、0から入ってるのでグラフの下の部分から描画します。
Float yCurrent = plotHeight.floatValue();
//前に計算した文字列の幅をもっかい計算するという愚行
int xPlotStart = getMeasuredWidth() - plotWidth;
for(int i=0; i< yLabels.size();i++){
//線を描きます
canvas.drawLine(xPlotStart, yCurrent, getMeasuredWidth(), yCurrent, paint);
//次の位置を計算
yCurrent = yCurrent - yEach;
} ほぼラベルを書いた時と一緒です!僕自身、コピペしてます!てか、ラベルの部分で描けば良かったのかも!まぁ、いいさ・・・。違うのがcanvas.drawLine(xPlotStart, yCurrent, getMeasuredWidth(), yCurrent, paint);
xの幅は固定で、yの位置だけ順番に上がっていってます。また、こんな感じにすれば、
//## yの線を描く!
Float yEach = plotHeight.floatValue()/yLineCount.floatValue();
//yLabelsは、0から入ってるのでグラフの下の部分から描画します。
Float yCurrent = plotHeight.floatValue();
//前に計算した文字列の幅をもっかい計算するという愚行
int xPlotStart = getMeasuredWidth() - plotWidth;
for(int i=0; i< yLabels.size();i++){
if(i==0){
paint.setStrokeWidth(2);
paint.setColor(Color.parseColor("#777777"));
}else{
paint.setStrokeWidth(1);
paint.setColor(Color.parseColor("#AAAAAA"));
}
//線を描きます
canvas.drawLine(xPlotStart, yCurrent, getMeasuredWidth(), yCurrent, paint);
//次の位置を計算
yCurrent = yCurrent - yEach;
} 0のラインだけ強調されます。
棒を描く!
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#777777"));
//それぞれの幅を計算
Float xEach = plotWidth.floatValue()/((Integer)xLabels.size()).floatValue();
//棒グラフに適度な余白を追加します。
Float barSpace = 20F;
//前に計算した文字列の幅をもっかい計算するという愚行
Integer xPlotStart = getMeasuredWidth() - plotWidth;
//最初のxの位置を計算
//xの開始位置
Float tmpXLeft = xPlotStart.floatValue() + barSpace ;
//xの終わり
Float tmpXRight = xPlotStart + xEach - barSpace ;
//valuesの値1に対する高さを計算
Float eachHeight = plotHeight.floatValue()/maxValue.floatValue();
for(int i=0;i<values.size();i++){
canvas.drawRect(tmpXLeft, plotHeight -(eachHeight*values.get(i)), tmpXRight, plotHeight, paint);
tmpXLeft = tmpXLeft + xEach;
tmpXRight = tmpXRight + xEach;
} xの開始位置(Left)は、yラベルの幅と棒の余白を考慮した場所となります。xの終了位置(Right)は、yラベルの幅と棒の幅を足して、余白部分を引いています。forの中で回しているんですけど、あとは、棒の大きさ分ずつヨコにずらしていってます
あと、yの位置なんですけど、まず、値1に対する高さを計算します。このvalue1に対する高さと実際の値を掛けたのが棒の上の位置(TOP)になります。yの下の位置(Bottom)は、グラフの高さで固定です。実行するとこんな感じ。

グラフですね。
でまぁ、問題点はいろいろあるんですけど、パッと見た感じで
- ラベルの大きさがぴったりすぎだ。ハゲ。
- 棒グラフに上の余白がほしいぞ。ハゲ
- デザインどーにかしろよ。ハゲ。
ラベルの大きさは、plotWidthとplotHeightを出す部分で文字列の幅・高さを2倍なんかにしてやるといいのかも。棒グラフの上の余白は、maxValueを計算したときに、1.2とか1.3とかを掛けてやれば、余白が生まれます。デザインに関しては、しらねーよハゲ。
あと、yのライン数は5に指定してるんですけど、valuesの値が全て5未満だった場合は変なことになるのかも。
追加したらいいかもな機能
- 棒グラフをタッチしたら反応する機能
- スクロール
スクロールは、HorizontalScrollViewなんかをうまい具合に仕込めばできます!
まとめたファイル!

若干修正して、Eclipseで作成したプロジェクトをまんまzip化したのがこちら!よくわからないんだけど、これってimportとかできんのかな・・・・?あと、このブログは無料ブログなんですけど、ファイル容量3MB中1.28MB使ってるらしい・・・。オワタ\(^o^)/

コメント
コメント一覧 (39)
Je revois mon m茅decin et nous voil脿 de nouvnike jordan en train d'essayer des trucs et des machins naturels. Le manque de challenge l'emp锚che de devenir un grand air jordan pas cher, ce qui est bien dommage 茅tant donn茅 le plaisir que l'on prend 脿 progresser au c聹ur d'une famille Simpson fid猫le 脿 elle-m锚me. Thee is evidence of the same too as air jordan pas cherMH saw it pofits dop by at east 20% in the aftemath of 911. L'habit vertLe costume, comme l'茅p茅e, est commun 脿 tous les nike jordans de l'Institut de France. un sens aigu du air jordan avec la mort.
[url=http://www.ishr.fr/nike-free-5.0-femme.html]nike free 5.0 femme[/url] Rejoignant les boxes de Guarato, Rapide Lebel montrait un tout autre visage et passait d'attentiste 脿 roulair jordan pas cher compresseur. l'air jordan de Roissy sous haute surveillancePour une politique 茅nerg茅tique europ茅enneArticle r茅dig茅 par yasminas2Avant de se poser la question de ce que la France devrait faire en mati猫re 茅nerg茅tique, il est urgent que l'Union europ茅enne parvienne 脿 fixer une v茅ritable strat茅gie 茅nerg茅tique europ茅enne. Cette fomation, qi dans ne cetaine mese essembe 脿 cee offete en dans es casses p茅paatoies en Fance, famiiaise es air jordan pas chers avec es gands pob猫mes de a science et de a vie contempoaine, ainsi qe, dans cetaines nivesit茅s, avec es gandes 艙ves itt茅aies et atistiqes d pass茅. Coco air jordan handbags obtained this inspiation fom he chidhood---- he nanny cod dea with a boad vaiety of stff with ot getting a bag in hand. D'o霉 ce conseil de grand-m猫re : boire l'air jordan pas cher de cuisson du riz en cas de diarrh茅e l茅g猫re.
[url=http://www.vaaa.fr/air-jordan-pas-cher.html]air jordan pas cher[/url]
<a href="http://www.alpillay.com/young.asp" >mulberry bayswater bag</a>
Canada Goose http://www.cambiehostels.com/SiteAnalytics.aspx
it sᥱems as though you relied оn the videߋ to make your point.
Yoᥙ clearⅼy know what youre talking about, why waste your intelligence on јust posting videos to your blog ԝhen you
could be giνing us something informative to read?
I'm starting a Ƅlog soon but have no coding қnowledge so I wanted to
gеt advice from someone with experience. Any help would be ᥱnormously appreciatᥱԁ!
ギフト以来低価格、高品質且つ豊富な品揃えで多くのお客様から支持と
信頼を得ております。
新作バッグや 財布など情報満載!激安特価で販売中!
主な販売2017年最新作ブランドコピー新品
100%品質保証!満足保障!
当店商品:送┃ 料┃ 無┃ 料┃
ノンプログラマー・プログラミング・ガイド <Loved it!
2018年春夏新作が入荷!
早くも2018年最新作が入荷激安屋は最高級のブランド スーパーコピー代引き(N品)専門店です!
高品質のブランド コピー、ブランド コピー 代引商品や情報が満載しています。
全部の商品は最高な素材と優れた技術で造られて、正規と比べて、品質が同じです!
当店の商品はすべて最高品質のN品でございます、
製造工場直営ですので他社に比べて大変お安く、最低価格を提示しております。
皆様方のご注文をお待ちしております。
I definitely enjoyed every little bit of it. I have you book
marked to look at new things you post…
人気 ルイヴィトン バッグ 2018年春夏新作,2018 ルイヴィトン 財布,ルイヴィトン 財布は優秀なデザインと実用性と個性完璧に融合する、高い人気を持っています。ブランド ルイヴィトン製品は非常にクオリティが高いことで多くの人に評価されています。時代に遅れなく、お客様に満足して頂くために、高級逸品を提供しております。お買い得で、品質も保証です。
自分使っても、誕生日や結婚式のプレゼントとしても最適です。
人気 ルイヴィトン バッグ 2018年春夏新作,2018 ルイヴィトン 財布,ルイヴィトン 財布は古典的なデザインで長期使っても飽きないです
ロレックス激安 https://www.jpbrandok.com/brand-20-fake-0-min-0-max0-attr0-4-sort_order%20Desc,goods_id-DESC.html
最新作ブランドコピールイヴィトン財布激安
偽物ブランド財布,偽物ブランド財布
シャネル財布偽物,ルイヴィトン財布,財布コピー
人気ブランド_バッグコピー_財布コピー
サングラス偽物_ベルトコピー_新作_スーパーコピー
バッグ、財布、小物などでございます専売店
★弊社は「信用第一」をモットーにお客様にご満足頂けるよう
★全物品運賃無料(日本全国)
★不良品物情況、無償で交換します.
★税関没収する商品は再度無料で発送します!
ホームページ上でのご注文は24時間受け付けております
ウブロコピー https://www.watchsjp.com/brand-216.html
ヴィトンコピー 販売階のほらを輸入する資格があって、
全国の第一項のナイロンのふろしき包みは傲慢なシリーズの
女性を配合して包んで、高級で派手で、
ハイエンドのファスナー、私達の採用の高級なファスナーは大工場のOEMからで、
ファスナーが順調で滑るのは丈夫で、高品質と高享受。
スーパーコピーN級品激安販売通販専門店 https://www.taka78.com/products-3118.html
日本的な人気と信頼を得ています。
安心、安全にお届けします
日本では手に入らない商品も、全て卸売りします。
価格、品質、自信のある商品を取り揃えておりますので
エルメス スーパーコピー キーケース https://www.kyoku66.com/goods-7450.html
人気商品コピー ブランド通販専門店。
全国送料無料!
当社は2019逸品が満載している好評度業界No.1ブランド コピー激安通販店です
店長お薦めは以下の商品:
パネライコピー時計,パネライブランドコピー,パネライN級品
IWCブランドコピー,IWC N級品,IWC時計コピー, IWC ポルトギーゼ
コピー専門店 https://www.bagraku.com/bagraku33/five/JC-GR5.html
N級品のブランドバッグ専門販売店当店では信用第一を基に、出荷した商品に対して品質と確実にお
届けできることを保障しています。
エルメススーパーコピー:http://www.buyoo1.com/brandcopy-21.html
ルイヴィトンコピーバッグ:http://www.buyoo1.com/brandcopy-27.html
オメガ時計コピー:http://www.buyoo1.com/brandcopy-4.html
弊社は最高級品質のロレックススーパーコピー時計販売優良店
本物品質時計コピー最も手頃な価格でお気に入りの商品を購入。
ウブロスーパーコピー時計:http://www.buyoo1.com/brandcopy-2.html
ロエベスーパーコピーバッグ":http://www.buyoo1.com/brandcopy-59.html
シャネルコピー通販":http://www.buyoo1.com/brandcopy-63.html
スーパーコピーブランドコピーN級品時計激安通販
ロレックスコピー販売、最高級ロレックススーパーコピーN級品偽物優良店
ブランドバッグ スーパーコピー,スーパーコピーブランド販売
ルイヴィトン モノグラム スーパーコピーイリュージョン レザー ブリーフケース
香港 スーパーコピー 女人街 地図 https://www.kopii.net/products/p4/index_2.html
イベント中です、
ロレックスコピー時計、パネライレプリカ時計、
シャネルニセモノ時計、ブライトリング偽物時計、
ウブロレプリカ時計、IWC イミテーション時計、
二年以内に人的破壊でない故障は無料で修理をします。
正規品と同等品質のコピー品を低価でお客様に提供します。
スーパーコピー ブルガリ リング レディース https://www.copy2021.com/product/detail/18724.htm
ブランドコピーの最高級品スーパーコピーを専門に取り扱うスーパーブランドコピー屋はこちらですよ。
確かな品質をもつスーパーブランドコピー新作満載!
ブランドコピーだどばれないスーパーコピーを買えるのはここですよ!
ブランドコピー,スーパーコピー,スーパーブランドコピーはロレックス デイトナ コピー、プラダ カナパ コピー、エルメス バーキン コピー等のスーパーコピー通販専門店です。
当店はロレックス デイトナスーパーコピー、ルイヴィトン 財布 コピー、ルイヴィトン 財布
スーパーコピーをはじめブランド時計、バッグ、財布偽物の外観から細部まで本物と同様です。
驚きの低価格でロレックス デイトナ コピー時計、エルメス バーキン コピーを通販します。
更に2年無料保証です。
ルイヴィトン 財布 スーパーコピー等の新品、高い品質、激安 、送料は無料です(日本国内)!ブランドコピーならにお任せ!
ヴィトン ポーチ スーパーコピー 代引き https://www.2bcopy.com/menu/menu_product-138.html
今回も過不足無く対応していただきました。
梱包材を開封しやすいように、テープの端を折って
あったりする心遣いがありがたいですね。
また、利用したいと思います。
スーパーコピー 代引き 服 メンズ https://www.kusuridonya.com/product/detail-11034.html
If you have been prescribed Plaquenil or Hydroxychloroquine for the treatment of malaria or rheumatoid arthritis and lupus, you can save money by purchasing your medication from a Canadian pharmacy. You can even get free standard shipping on all orders over $99. It’s never been easier to access affordable prescription drugs from licensed online pharmacies in Canada.
<a href="https://plaquenil4people.top">buy plaquenil for sale</a>
日本的な人気と信頼を得ています。
安心、安全にお届けします
日本では手に入らない商品も、全て卸売りします。
価格、品質、自信のある商品を取り揃えておりますので
jacob 時計 スーパーコピー 口コミ https://www.wellwatchs.com/goods-copy-1366.html
日本的な人気と信頼を得ています。
安心、安全にお届けします
価格、品質、自信のある商品を取り揃えておりま すので、
高級腕時計(N級品),スーパーコピー時計(N級品),財布(N級品)バッグ(N級品),靴(N品),指輪(N級品),ベルト(N級品),マフラー (N級品)
★100%品質保証!満足保障!リピーター率100%!
★商品数も大幅に増え、品質も大自信です。
★スタイルが多い、品質がよい、価格が低い!
★顧客は至上 誠実 信用。
★歓迎光臨★送料無料(日本全国)
ルイヴィトン コインケース スーパーコピー https://www.wellwatchs.com/goods-copy-9753.html
Increase your Visibility Boost Your Seo Rank - Get Organic Traffic From Google. Ranking in Google isn’t hard. All you need is a healthy number of backlinks from referring domains that have authority and trust in Google’s eyes.
This Backlinks Service Benefits:
1. Easily get Google rankings
2. Get a lot of traffic from Google
3. You can earn from the website in different ways
4. Increase Domain Authority (DA)
Quality guaranteed !
PRICE - 20$
WebSite - https://goo.su/ZUHZ
激安、安心、安全にお届けします.
[url=https://www.bbagok.com]スーパーコピー腕時計[/url]
店長: 山本 優希
ご入金が確認できてから1週間でお届け致します。
注文割引開催中
品数豊富、色々な選択があります。
消費税無し!