2015年7月30日木曜日

MAC でデフォルトのテキストエディタを変更する方法

ファイルを右クリックから、「このアプリケーションで開く」から選択しても、開けるもののデフォルトになってくれない。

以下参照
http://www.lastday.jp/2011/10/25/mac-open-favorite-app-as-default

同じく右クリックから、「情報を見る」で、一覧から「このアプリケーションで開く」の項目を選択し、アプリケーションを選択後、「すべてを変更…」押下で、選択したものがデフォルトになってくれる。

2015年7月29日水曜日

Ruby での加算子

よくある「++」はないので、
hoge += 1
とする。

それどころか、へたに++なんていれると、次の行が文法エラーとなったり、次の行の何かと連結できてしまうと、おかしな挙動になる。
++がダメ、とピンポイントで指摘してくれないので、ハマった。。

2015年7月28日火曜日

static

android にて、変数をstaticで持たせるのは基本NGとのこと。

2015年7月15日水曜日

画面を縦に固定

マニフェストの activity タグに以下を記載。
android:screenOrientation="portrait"

シングルトン

以下のサイトを参考に。
https://sites.google.com/site/androidappdojo/home/lesson/section04/section0405

クラスを使うときの new を呼び出し元ではなく、呼び出し先のそのクラス自身に任せる的な。

コンストラクタは、private にして制限。
getInstance() で呼び出すように書く。

とはいえ、コンストラクタがpublic じゃないと、画面回転させた時などに落ちる。

2015年7月14日火曜日

ダイアログ フラグメント

public class MainActivityFragment extends Fragment {
public MainActivityFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button button;
button= (Button)getView().findViewById(R.id.button_form);
button.setOnClickListener(new Form());
}
private class Form implements View.OnClickListener {
@Override
public void onClick(View view) {
final Context c = getActivity();
if (c != null) {
showDialog();
}
}
}
void showDialog() {
DialogFragment newFragment = MyAlertDialogFragment.newInstance(R.string.hode);
newFragment.setTargetFragment(this, R.string.hode);
newFragment.show(getFragmentManager(), "dialog");
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case R.string.hode:
break;
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub
public class MyAlertDialogFragment extends DialogFragment {
public static MyAlertDialogFragment newInstance(int title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
EditText editText = new EditText(getActivity());
return new AlertDialog.Builder(getActivity())
.setTitle(title)
.setView(editText)
.setPositiveButton("はい",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
doPositiveClick();
}
}
)
.setNegativeButton("いいえ",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
doNegativeClick();
}
}
)
.create();
}
public void doPositiveClick() {
Intent data = new Intent();
String text = "hoge";
data.putExtra(Intent.EXTRA_TEXT, text);
Fragment callerFragment = getTargetFragment();
callerFragment.onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, data);
}
public void doNegativeClick() {
}
}
view raw gistfile1.java hosted with ❤ by GitHub
ダイアログ出すにも、DialogFragment を使えということなのでメモ。
※参考URL
http://developer.android.com/reference/android/app/DialogFragment.html#AlertDialog
http://quesera2.hatenablog.jp/entry/2014/04/09/003146
のFragment→Fragment→Fragment のところ。
http://www.fkmsoft.jp/blog/software/android/fragment/dialog_2.html

アラートダイアログ以外を表示するには、 new AlertDialog.Builder の部分を変更。
ただし表示するものによって、必須の指定があるので、要確認。
たとえば、ドラムロールのTimePickerDialog だと、「~~ extends DialogFragment implements TimePickerDialog.OnTimeSetListener」として、Override で onTimeSet が必須になる。あとなぜか return new ~~~ .create(); じゃだめで、変数宣言して、それをリターンしてやらないとエラーだった。

また、.setView のところ、上記の例では EditText のウィジェットをjavaで生成して入れているが、これも好きなもの(seekbarとか)を入れられるし、レイアウト(XML)で凝ったものでも作ってインフレートしてからセットすることも試してないが、可能かと。

なお、フラグメントから呼び出したダイアログフラグメントより、呼び出し元のフラグメントへ処理を返す方法も記述。
呼び出す際に setTargetFragment しておき、呼び出し先で、getTargetFragment にて取得し、onActivityResult で返してやる。

※最後に。 上記の例では、フラグメントと、ダイアログフラグメントを分離しているが、
フラグメントクラス内にダイアログフラグメントを記述する場合は、public static とする。
「public class MyAlertDialogFragment extends DialogFragment」
 ↓
「public static class MyAlertDialogFragment extends DialogFragment」
意味としては、これは親クラスとは関係ないよ、という宣言。

2015年7月10日金曜日

Java メモ

・数値を文字に変換
String str = Integer.toString(num);

Calendar

カレンダークラスで日時などを指定する方法

・共通
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.setTimeZone(TimeZone.getDefault());

・毎日
例えば11時10分0秒なら、
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 10); //02などはいけるが、なぜか08以降はダメ。0不要か。
calendar.set(Calendar.SECOND, 0);
※時間指定のみなので、毎日となる。
※なお、秒を指定しないと1分程度遅れた。0秒指定で端末時間でジャスト起動。

・比較
各変数は、以下とする。
現在時刻:calendarNow
設定時刻:calendarSet
int num = calendarNow.compareTo(calendarSet);
if(num>0){
    Log.d("time","現在時刻が、設定時刻より進んでいる。");
}

・メソッドなど詳しく紹介しているサイト
http://www.techscore.com/tech/Java/JavaSE/Utility/8/
add  と roll の違いなど。

・翌日
今日のCalendar.DAY_OF_YEARがsetされているor最初から何も指定していないとして、
calendar.add(Calendar.DAY_OF_YEAR, 1);
すれば、翌日。
Calendar.DAY_OF_YEAR は一年のうちで、今日が何日目か。
なお年末でも大丈夫。

・時刻取得
get メソッドで取得。何もsetしてなければ、現在時刻を取ってくる。
int hour = calendarNow.get(Calendar.HOUR_OF_DAY);
※何かsetしていると、その設定したものを取ってくる。

・正確さ
秒まで指定しないと、1分くらい遅れた。(0秒指定で、分変わりジャスト)

・備考
calendar.set(Calendar.MINUTE, 5);
みたいに数字を書く。
たとえば05という風に書くと、08からなぜかエラー。

2015年7月9日木曜日

R.id.hoge とかのリソースを動的に読み込む方法

以前の記事で、最後に触れている
http://yazakikenji.blogspot.jp/2011/12/imageview.html

が、再掲。

例。
ImageView imageView;

imageView = (ImageView) getView().findViewById(R.id.imageView1);

同じことを動的にやるには、
String str = "1";

imageView = (ImageView) getView().findViewById(getResources().getIdentifier("imageView"+str,"id",getActivity().getPackageName()));

実際には、上記のstrは数字(連番)で持たせて処理の中で、forループなどで使う形になると思う。

・getIdentifier の詳細
第一引数は、XML ファイルで定義したIDを入れる。
同一の名前で最後に数字を連番でつけるのが楽か。(名前が違うと当然エラーになるので注意!XML側でつけたIDの命名規則が一部違っているとかもそう。)
第二引数は、
R.id なら"id"
R.drawable なら"drawable"
となる。
第三引数は、パスの指定だが、それはパッケージ名となる。getPackageName() を使わず、直書きでもいい。なおフラグメントで使うことを想定して、getActivity() している。

2015年7月7日火曜日

レイアウトのクリック可能範囲と、バックグラウンドの反応

java 側にて、OnClickListener を設定したり、
Layout (XML) 側にて、クリック可能なものを設置した場合、
クリック可能範囲が、(なんと表現すべきか)XMLタグの深い方(中にある方)が優先される模様。

なので、例えば表のLinearLayout のbackground に、クリックしたら色が変わるような設定のファイルを置いても、(もちろんclickable="true")
その内部のLinearLayout でもTextView、ImageView でも、クリック可能になった場合、そのクリックイベントが優先されるため、表のLinearLayout の設定は生きない。

もっとも、何かしら隙間があれば、そこをタッチすれば、そこだけは反応してくれるが。

Fragment の作成、遷移

フラグメント
public class TestActivity extends FragmentActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
Fragment f = TestFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, f)
.commit();
}
}
}
view raw gistfile1.java hosted with ❤ by GitHub
public class TestFragment extends Fragment {
public static TestFragment newInstance(){
return new TestFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_test, container, false);
return rootView;
}
}
view raw gistfile1.java hosted with ❤ by GitHub

ListFragment の使い方

リストフラグメント。
実装するクラスに、extends ListFragment して、以下。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_test, container, false);
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
List<BindData> data = new ArrayList<BindData>();
data.add(new BindData("1", "1の詳細"));
data.add(new BindData("2", "2の詳細"));
MyAdapter adapter = new MyAdapter(
getActivity(),R.layout.test, data);
setListAdapter(adapter);
}
private class BindData {
String hoge;
String piyo;
public BindData(String t1,String t2) {
this.hoge = t1;
this.piyo = t2;
}
}
public class MyAdapter extends ArrayAdapter<BindData>{
private LayoutInflater inflater;
private int layoutId;
TextView textHoge;
TextView textPiyo;
List<BindData> objects;
public MyAdapter(Context context, int layoutId, List<BindData> objects) {
super(context, layoutId, objects);
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.layoutId = layoutId;
this.objects = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null || convertView.getId() != layoutId) {
convertView = inflater.inflate(layoutId, parent, false);
textHoge = (TextView) convertView.findViewById(R.id.textHoge);
textPiyo = (TextView) convertView.findViewById(R.id.textPiyo);
}
// BindData data = getItem(position); これでも取得可能。objects不要。
BindData data = objects.get(position);
textHoge.setText(data.hoge);
textPiyo.setText(data.piyo);
return convertView;
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Fragment f = TestFragment.newInstance();
Bundle bundle = new Bundle();
switch ((int)id){
case 0:
bundle.putInt("test", (int)id);
f.setArguments(bundle);
getFragmentManager()
.beginTransaction()
.replace(android.R.id.content, f)
.addToBackStack(null)
.commit();
break;
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
setListAdapter(null);
}
view raw gistfile1.java hosted with ❤ by GitHub
fragment_test.xml
id のとこ、android:list とするのね。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fragment_test"/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/android:list" />
</LinearLayout>
view raw gistfile1.xml hosted with ❤ by GitHub
test.xml は省略。

なお、リストをクリックすると、別のフラグメントが起動するよう処理を書いている。
その際、newInstance() などと書いているが、この手の実装は次の投稿で。

2015年7月6日月曜日

ListView で文字を縦に2つ並べた時に、最初にタッチすると、なぜか間に区切り線が出てくる件。

なんだかよく分からないが、Layout の高さを指定したら、直った。

LinearLayout で作成したリスト的なものに、ListViewで使われる罫線を入れる。また、タッチした時に背景の色が変わるようにする。

・罫線
layout 配下に適当な名前で、以下を作成。
hoge.xml
<View xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="1dp" android:background="?android:attr/listDivider" />

あとは、差し込みたい場所に
<include layout="@layout/hoge" />
で入れる。


・タッチ時背景色変更
プロジェクト作成時に、自動的に?作られていたものを設定。
android:background="@drawable/stamp_item_bg"

stamp_item_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_pressed="true"
        android:drawable="@drawable/stamp_item_bg_pressed" />
    <item android:drawable="@android:color/transparent" />

</selector>

2015年7月2日木曜日

リストにヘッダーをセットした場合の注意点

リスト表示のヘッダー、フッターに何かを挿入したい場合。

TextView textView = new TextView(getActivity());
textView.setText("This is Header");
getListView().addHeaderView(textView, null, false);

アダプターの追加
setListAdapter(adapter);

みたいに、
setListAdapter() する前に addHeaderView() してあげる必要がある。

しかし、ここで注意点。

このままだと、他画面に移って、また上記の画面に戻った場合、エラーで落ちる。
理由は、既にsetListAdapter() されてるから addHeaderView() できません。

つまり、アダプターが破棄されずに残っている。

これを回避するには、
@Override
public void onDestroyView() {
    super.onDestroyView();
    setListAdapter(null);
}

このように、onDestroyView() にて、アダプターをnull してやる。

なお、アウトオブメモリー対策にもなる模様。

AndroidStudio で、Uploading file で止まる。

ビルド中、
Uploading file
 local path: ~~~.apk
 remote path: ~~~
で止まってしまう現象。

どうもソースツリーとかで他人のプロジェクトを触っている時に発生。

メニューから、
Build -> Clean Project
をして、直ったっぽい。

と思ったら、再発。

プロジェクトのルートで、
./gradlew clean packageDebug
で様子見。

…また再発。

どうもUSBケーブルが悪かったようで、交換したら直った。

追記)
交換後も、たまに再発。
どうも端末にもよるらしい。
また、人に聞いたら、やっぱり端末によっては、かなり頻発するらしい…