2013年4月23日火曜日

ピッカー(NumberPicker)

Version11から、使えるようになった機能のNumberPickerを紹介します。

指をスライドすると数値がくるくる回って、スマホ感を演出できます。

注意点としては、Version11以降しか対応していないことです。

丁度スマホが流行りだしたAndroid2.2、Android2.3の頃の端末に対応していないのは使いづらい点ではありますが。。。。


また、Version11より前でも使えるライブラリ(個人で作った)も公開されていますが、端末によっては動かない等ありますので、あんまりお勧めはません。。。


■サンプルソース
package com.pulepule.linear;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.Toast;
import android.widget.NumberPicker.OnValueChangeListener;

public class MainActivity extends Activity implements OnValueChangeListener{
 
    //レイアウト用の定数
    final int WC = ViewGroup.LayoutParams.WRAP_CONTENT;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //基レイアウトの作成
        LinearLayout oLayout = new LinearLayout(getApplicationContext());
        //基レイアウトを画面に設定
        setContentView(oLayout);
  
        //背景を黒にする(見やすいように)
        oLayout.setBackgroundColor(Color.BLACK);
        //真ん中にパーツを寄せる。 | 区切りで複数記述できます。
        oLayout.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL );

        //データピッカーの生成
        NumberPicker oPicker = new NumberPicker(getApplicationContext());
        //データピッカーの最小値を設定
        oPicker.setMinValue(3);
        //データピッカーの最大値を設定
        oPicker.setMaxValue(1120);
        //データーピッカーの背景色を
        oPicker.setBackgroundColor(Color.BLUE);
        //値が変更された時に通知するリスナー
        oPicker.setOnValueChangedListener(this);

        oLayout.addView(oPicker, new LinearLayout.LayoutParams(WC, WC));
        //値をピッカーに設定
        oPicker.setValue(5);
    }

    @Override
    public void onValueChange(NumberPicker picker, int iBefValue, int iActValue) {
        Toast.makeText(getApplicationContext(), String.valueOf(iActValue), Toast.LENGTH_SHORT).show();
        Log.d("ひとつ前の選択",String.valueOf( iBefValue ));
        Log.d("picker.getValue()",String.valueOf( picker.getValue()));
    }
}

■実行結果




こんな感じでできました。



//データピッカーの生成
NumberPicker oPicker = new NumberPicker(getApplicationContext());

//データピッカーの最小値を設定
oPicker.setMinValue(3);
//データピッカーの最大値を設定
oPicker.setMaxValue(1120);



上記の処理でピッカーの生成と
ダイヤルの最小値と最大値を設定しています。

//値をピッカーに設定
oPicker.setValue(5);

この処理で、初期値を設定しています。
現在設定されている値を初期値にするのが良いでしょう。

現在、選択されている値の取得は

picker.getValue()

int型で返されます。


2013年4月20日土曜日

R.~でエラーがでる, 画像や文言が読み込めない(Resフォルダー参照エラー)

Eclipseを使っていて、
Resフォルダー内の資材がソースに取り込めない事ありませんか??

ちゃんとファイル名も拡張子もあっているのに。。。。何で??

っていうときは、「gen」フォルダの「R.java」ファイルを見ましょう!

static final intで取り込みたいファイルあるいは変数が宣言されているかの確認をして、
宣言されてなかったら、ソースファイルを全て一旦保存して、
「プロジェクト」→「クリーン」

再ビルドして、上手くいくか確認してみましょう!!

それでも、上手くいかない場合には、
「プロジェクト」→「自動的にビルド」のチェックを外す
→「Eclipse」の再起動

「プロジェクト」→「クリーン」

これで、どうでしょうか?

自分はこの方法で上手くいきます。

それと、Rのインポートは、

manifestファイルで指定したパッケージ名 + .R

Android.Rではなく、パッケージ名にRで!!

2013年4月17日水曜日

実行エラー caused by android.os.networkonmainthreadexception

android.os.networkonmainthreadexception

caused by android.os.networkonmainthreadexception

Android3.0以降に発生!!

メインスレッドでサーバー処理(HTTPリクエスト)
をすると発生!!

AsyncTaskで別スレッドを作成して、そこで処理させると解決!!

2013年4月15日月曜日

エラー  android.util.AndroidRuntimeException: requestFeature() must be called before adding content

 android.util.AndroidRuntimeException: requestFeature() must be called before adding content


というエラーがでた。。


確認したところ、


setContentView

の後に、
requestWindowFeature
をすると発生すらしいです。

requestWindowFeature
setContentView

にするとOKです。


2013年4月10日水曜日

グリッドデザイン/テーブルビュー(GridView,BaseAdapter)


スマホでよく見かける表示方法のグリッド表示についてです。
使い方はリストビューとだいたい同じ感じで使えます。

■グリットビューの生成
GridView  oGridView = new GridView(Context);

■グリットビューの列数を指定
oGridView.setNumColumns(int);

横に何個並べるかの指定です。
-1にすると画面サイズに最適な列数が選ばれるようです。
ソースに-1と直書きしたくないので、
用意されている定数で記述したいのですが、用意されている定数を私はしりません。

■Adapterを設定
oGridView.setAdapter(ListAdapter);

アダプターに1セルあたりの情報を持ちます。

■サンプルソース
package com.example.sumple01;

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

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends Activity {

    private List oGridList = new ArrayList();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //基礎画面の作成
        LinearLayout oLyout = new LinearLayout(getApplicationContext());
        //グリットビューの生成
        GridView  oGridView = new GridView(getApplicationContext());

        //基礎画面を画面に設定
        setContentView(oLyout);
        //基礎画面にグリットビューを追加
        oLyout.addView(oGridView);

        //グリットビューのセル?の作成
        for (int i = 0; i < 10; i ++){
            //配列にタイトルと画像を格納
            oGridList.add(new GridClass(String.valueOf("番号:" + i), R.drawable.ic_launcher));
        }

        //列数を設定(-1にするとAUTO_FIT)
        oGridView.setNumColumns(3);
        //グリットビューに各セルの情報を設定
        oGridView.setAdapter(new ListAdapter());

    }

    private class ListAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            //グリッド総数
            return oGridList.size();
        }

        @Override
        public Object getItem(int position) {
            //配列の中身
            return oGridList.get(position);
        }

        @Override
        public long getItemId(int position) {
            //現在の配列の場所
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView title;
            ImageView imag;
            View v = convertView;

            if(v==null){
                //レイアウト用の定数
                final int WC = ViewGroup.LayoutParams.WRAP_CONTENT;

                //グリットビューの1マス内のレイアウトを作成
                LinearLayout oGridLyout = new LinearLayout(getApplicationContext());
                oGridLyout.setGravity(Gravity.CENTER_HORIZONTAL);
                //上から下にアイテムを追加
                oGridLyout.setOrientation(LinearLayout.VERTICAL);
                //イメージビューを生成
                ImageView oGridImage = new ImageView(getApplicationContext());
                //テキストビューを生成
                TextView oGridText = new TextView(getApplicationContext());
                //判別用にタグをつける
                oGridImage.setTag("CellImage");
                oGridText.setTag("CellTitle");

                //グリットビュー用のレイアウトに追加
                oGridLyout.addView(oGridImage, new LinearLayout.LayoutParams(WC, WC));
                oGridLyout.addView(oGridText, new LinearLayout.LayoutParams(WC, WC));
                v = oGridLyout;
            }

            //配列から、アイテムを取得
            GridClass oGrid = (GridClass)getItem(position);

            if( oGridList != null){
                //タグからテキストビューを取得
                title = (TextView) v.findViewWithTag("CellTitle");
                //取得したテキストビューに文字列を設定
                title.setText(oGrid.Get_Title());

                //タグからイメージビューを取得
                imag = (ImageView) v.findViewWithTag("CellImage");
                //イメージビューに画像を設定
                imag.setBackgroundResource(oGrid.Get_Image());
            }

            return v;

        }
    }

}
■クラスファイル
package com.example.sumple01;

public class GridClass{
    private String Title;
    private int imgRid;
 
    public GridClass(String title, int resId){
        Title = title;
        imgRid = resId;
    }
 
    public String Get_Title(){
        return Title;
    }
 
    public int Get_Image(){
        return imgRid;
    }
}
■実行結果



それっぽい感じになりました。

ソースを見ると、
最初に定義しているこの部分が地味に大切で
private List<GridClass> oGridList = new ArrayList<GridClass>();

リスト型のグリッドクラスを作成しています。
グリッドクラスって、何??

public class GridClass{
■クラスファイル
で作成したクラスです。


グリッド表示時に1つのセルに必要な情報を格納するクラスです。

このクラスを下記のように書き換えて


public class GridClass{
    public String Title;
    public int imgRid;
    public GridClass(String title, int resId){
        Title = title;
        imgRid = resId;
    }
}


ListAdapterクラスの文字列と画像を設定する記述を
下記のように変更するとGridClassの用途がわかりやすくなると思います。
構造体のような使い方をしているだけです。
-------------------------------------------
//取得したテキストビューに文字列を設定
title.setText(oGrid.Title);
imag.setBackgroundResource(oGrid.imgRid);
-------------------------------------------

//グリットビューのセル?の作成
for (int i = 0; i < 10; i ++){
   //グリッドクラスを生成して、配列にタイトルと画像を格納
   oGridList.add(new GridClass(String.valueOf("番号:" + i), R.drawable.ic_launcher));
}

この処理で先ほど作成した、リストにグリッドクラスの情報を格納していきます。

//グリットビューに各セルの情報を設定
oGridView.setAdapter(new ListAdapter());


こちらの処理で、グリッドビューにアダプタの情報(BaseAdapterをextendsしているクラス)を渡しています。

BaseAdapterをextendsしているクラスについてですが、、

getCount()の数だけ、処理は行われます。

if (v==~
の中で1セルのレイアウトを作成して、

if(oGrid~
の中で、その作成したレイアウトに必要な情報を
oGridListから取得して、レイアウトに設定しています。

BaseAdapterをextendsするクラスは
結構よく使うので、使い方を覚えておきましょう。


2013年4月9日火曜日

ラジオボタン-02(カスタマイズ編)


ラジオボタンをカスタマイズして、ちょっとそれっぽくしてみようと思います。

xmlで作成した、レイアウトファイルを読み込んでそれっぽく作ります。

なお、ラジオボタンの使い方に関しては、
ラジオボタン-01(RadioGroup, RadioButton)

xmlで背景を作成する方法に関しては
xmlで背景を変更(android:shape=)

を参照してください。

■サンプル
●MainActivity
package com.example.sample;

import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity implements OnCheckedChangeListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       //レイアウトの生成
        LinearLayout layout=new LinearLayout(getApplicationContext());
        //上から下にオブジェクトを配置するよう設定
        layout.setOrientation(LinearLayout.VERTICAL);

        //画面表示の設定
        setContentView(layout);

        //レイアウトパラム定数(縦横の長さの定数)の格納
        int WC = ViewGroup.LayoutParams.WRAP_CONTENT;
        int MP = ViewGroup.LayoutParams.MATCH_PARENT;
        
        //ラジオグループの登録
        RadioGroup oRadiGrop = new RadioGroup(getApplicationContext());
        //チェック時の処理を通知させる 
        oRadiGrop.setOnCheckedChangeListener(this);
        //左から右へとオブジェクトを配置
        oRadiGrop.setOrientation(LinearLayout.HORIZONTAL);
        oRadiGrop.setGravity(Gravity.CENTER_HORIZONTAL);

        //ラジオグループをレイアウトに追加
        layout.addView(oRadiGrop, new LinearLayout.LayoutParams(MP, MP);

        //レイアウトパラムの作成
        LayoutParams oLayPar = new LinearLayout.LayoutParams(WC, WC);
        
        //ラジオグループにラジオボタンを追加
        oRadiGrop.addView(Make_RadioButton(0, "ROW"), oLayPar);
        oRadiGrop.addView(Make_RadioButton(1, "MID"), oLayPar);
        oRadiGrop.addView(Make_RadioButton(2, "HIGH"), oLayPar);
        
    }
 
    @Override
    public void onCheckedChanged(RadioGroup oRG, int Id) {
     //無選択状態のidは-1
        if (Id ==-1)return;
        //IDに紐づくテキストを取得
        String sText = String.valueOf(((RadioButton)findViewById(Id)).getText());
        //現在チェックされているidを取得
        int iActiveID = oRG.getCheckedRadioButtonId();
        //選択されたIDに紐づくテキストを表示
        Toast.makeText(getApplicationContext(), sText ,Toast.LENGTH_SHORT).show();
        //アクティブなIDを表示
        Toast.makeText(getApplicationContext(), String.valueOf(iActiveID),Toast.LENGTH_SHORT).show();
    }

    private RadioButton Make_RadioButton(int id, String sTitle){
        //ラジオボタンの生成
        RadioButton oRadioBtn = new RadioButton(this);
        //ラジオボタンにIDを設定
        oRadioBtn.setId(id);
        //ラジオボタンに文字列を設定
        oRadioBtn.setText(sTitle);
        //ラジオボタンを消す
        oRadioBtn.setButtonDrawable(android.R.id.empty);
        //作成したxmlを背景に設定
        oRadioBtn.setBackgroundResource(R.drawable.stylebutton);

        //ラジオボタンを返す
        return oRadioBtn;
    }
}
●xmlファイル
stylebutton.xml
  
  
  
    
      
      
      
      
    
  
  
  
  
    
      
      
      
      
   
 
  

■実行結果





メインの処理は特に変わったことはしていませんが、

//左から右へとオブジェクトを配置
oRadiGrop.setOrientation(LinearLayout.HORIZONTAL);
ラジオボタンを横に並べる記述です。
何も記述しないと縦に縦にラジオボタンが配置されます。

oRadiGrop.setGravity(Gravity.CENTER_HORIZONTAL);
ラジオボタンを真ん中に集める処理です。

Make_RadioButton関数の
//ラジオボタンを消す
oRadioBtn.setButtonDrawable(android.R.id.empty);
//作成したxmlを背景に設定
oRadioBtn.setBackgroundResource(R.drawable.stylebutton);

が今回のポイントで
//ラジオボタンを消す
oRadioBtn.setButtonDrawable(android.R.id.empty);
で、ラジオボタンのチンチクリンの丸いチェックを表示させないようにしています。
これをすると、ラジオボタンらしさは消えます。

//作成したxmlを背景に設定
oRadioBtn.setBackgroundResource(R.drawable.stylebutton);
この処理で、なくしたラジオボタンらしさに、新たな個性を付け加えます。


ではでは、xmlファイルを見ていきましょう。

<!-- 選択時 -->
<item
  android:state_checked="true"
  android:shape="rectangle">

<!-- 未選択時 -->
  <item
    android:state_checked="false"
    android:shape="rectangle">

この記述で、ラジオボタン選択中に呼ぶアイテムとラジオボタン未選択時に呼ぶ
アイテムとを区別しています。

<corners 
  android:radius="1dip" />
この処理によって、ボタンの4角を少しだけ、曲げています。

また、選択時に
<stroke
android:width="2dp"

をすることで、ボタンを少し小さく見せています。ほんの少しですが。。。
押されている感を出しています。

グラデーションも自分なりに工夫してみましたが。。。どうでしょうか??


デザインとか何かいろいろ面倒なことが多いのですが、
これを用いることで、iPhone風のAndroidアプリも
作成できます。

「iPhoneとまったく同じで作って!!」

みたいな仕様が来たときはこんな感じでパワープレイで乗り切りましょう!!


てか、そんな仕様を私は絶対に認めないけど。。
と言いつつも、結局折れてしまいますが。。

2013年4月3日水曜日

ラジオボタン-01(RadioGroup, RadioButton)

ラジオボタンは複数の選択肢から、
ユーザーに1つだけ選んでもらう際に利用されます。
個人的にはラジオボタンは好きではないのですが、
そういう事を言うと
「システムの人って、本当に面倒くさい!!」
とか思われそうなので、心にしまっています。
はい。


ラジオボタン生成の仕方は
RadioButton oRadioBtn = new RadioButton(this);

さらに

//ラジオボタンにIDを設定
oRadioBtn.setId(int);
//ラジオボタンに文字列を設定
oRadioBtn.setText(String);

idを設定することにより、一意に認識することができるようになり、
setTextで表示する文字列を設定できます。

こんな感じでOKです。

ただ、生成時の引数thisをgetApplicationContext()にする
とsetTextの文字が画面に表示されませんでした。。

壊れかけのラジオボタン!!



ラジオボタンの生成はこれで大丈夫なのですが、
複数のラジオボタンを束ねるマネージャー的な
oRadiGropを利用します。

//生成
RadioGroup oRadiGrop = new RadioGroup(getApplicationContext());

//チェック時の処理を通知させる 
oRadiGrop.setOnCheckedChangeListener();

//ラジオグループにラジオボタンを追加
oRadiGrop.addView(RadioButton, LayoutParams);


ラジオグループを作成して、そこに各ラジオボタンを追加するイメージです。
また、生成時に引数をgetApplicationContext()にしてますが、今のところ
問題ありません。笑


■サンプルソース
package com.example.sample;

import android.os.Bundle;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity implements OnCheckedChangeListener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //レイアウトの生成
        LinearLayout layout=new LinearLayout(getApplicationContext());
        //上から下にオブジェクトを配置するよう設定
        layout.setOrientation(LinearLayout.VERTICAL);

        //レイアウトパラム定数(縦横の長さの定数)の格納
        int WC = ViewGroup.LayoutParams.WRAP_CONTENT;
        //レイアウトの横幅・縦幅を設定
        LayoutParams oLayPar = new LinearLayout.LayoutParams(WC, WC);

        //画面表示の設定
        setContentView(layout);
        
        //ラジオグループの登録
        RadioGroup oRadiGrop = new RadioGroup(getApplicationContext());
        //チェック時の処理を通知させる 
        oRadiGrop.setOnCheckedChangeListener(this);
  
        //ラジオグループにラジオボタンを追加
        oRadiGrop.addView(Make_RadioButton(0,"ON"), oLayPar);
        oRadiGrop.addView(Make_RadioButton(1,"OFF"), oLayPar);
        
        //ラジオグループをレイアウトに追加
        layout.addView(oRadiGrop, oLayPar);
    }
 
    @Override
    public void onCheckedChanged(RadioGroup oRG, int Id) {
     //無選択状態のidは-1
        if (Id ==-1)return;
        //IDに紐づくテキストを取得
        String sText = String.valueOf(((RadioButton)findViewById(Id)).getText());
        //現在チェックされているラジオボタンのidを取得
        int iActiveID = oRG.getCheckedRadioButtonId();
        //選択されたIDに紐づくテキストを表示
        Toast.makeText(getApplicationContext(), sText ,Toast.LENGTH_SHORT).show();
        //アクティブなIDを表示
        Toast.makeText(getApplicationContext(), String.valueOf(iActiveID),Toast.LENGTH_SHORT).show();
    }
    
    
    private RadioButton Make_RadioButton(int id, String sTitle){
        //ラジオボタンの生成
        RadioButton oRadioBtn = new RadioButton(this);
        //ラジオボタンにIDを設定
        oRadioBtn.setId(id);
        //ラジオボタンに文字列を設定
        oRadioBtn.setText(sTitle);
        //ラジオボタンを返す
        return oRadioBtn;
    }
}
■実行結果

onCheckedChanged関数内の
String sText = String.valueOf(((RadioButton)findViewById(Id)).getText());



こちらの処理はチェックされている文字列を取得しています。

第2関数のIDから、ラジオボタンを探して、そのラジオボタンに設定されているテキスト
を取得して、文字列で返しています。

//現在チェックされているidを取得
int iActiveID = oRG.getCheckedRadioButtonId();

こちらの処理はリスナー内で読んでいますが、リスナー外でも全然呼べます。
なので、現在の状態が知りたいときにサクッと呼んでください。



//チェック時の処理を通知させる 
oRadiGrop.setOnCheckedChangeListener(this);

また、今回はチェックされたときにimplementのメッソッドが呼ばれていますが、
他にも実装方法はたくさんあるので、いろいろ試してみてください。

話は戻りますが、AndroidのViewパーツを生成時にthisを渡すのがいいのでしょうか??