Android用のシンプルタイムマネージャー

私はここで、Android向けのアプリケーションの作成方法に関する記事を書くことにしました。 簡単な時間管理者が書きます。 このパートでは、プログラム自体を作成し、アニメーションを使用したインターフェイスをアタッチし、次に興味深い場合は、プログラムもバックグラウンドで動作するようにサービスを作成します。



考慮されるもの:





明確にするために、これらすべての仕組みのスクリーンキャストを追加しました。



そこで、Android用のシンプルな時間マネージャーを作成しています。



SDK + Eclipseがすでにインストールされているとします。





Eclipseを実行し、[ファイル]-[新規]-[その他]に移動します。

開いたウィンドウで、[Android-Android Project]を選択します。





そのようなウィンドウが開きます。

パラメータを入力します。

プロジェクト名 -これはプロジェクトの名前であり、現在のワークスペースで一意である必要があります。

BuildTarget-プロジェクトがビルドされているOSバージョン。 1.5のプロジェクトを収集する場合、1.6と2.1の両方で開始され、1.6でビルドする場合は1.5では開始されないことに注意してください。

アプリケーション名 - アプリケーションの名前 。 メインメニューに表示され、そこから起動できます。

パッケージ名 -com。<オフィス名>。<アプレット名>

アクティビティの作成 -アプリケーションを実行するアクティビティの名前。

プロジェクトの作成後に画面が撮影されたため、同じ名前のプロジェクトが既に作成されているため、上から「ファイルが既にあります...」というエラーが表示される場合があります。

完了をクリックします。



インターフェース





ここで、タイマーのテキストのサイズは同じである必要がありますが、アニメーションのために増減する必要があります。

これを行うには、アプレットの上部にある影用のImageViewと、タイマー用とボタン用の2つのLinearLayoutの3つの子を持つRelativeLayoutを使用します。

時間と機会があれば、すべてを自分で描くことができますが、すべての消防士に対して、すべてのグラフィック要素を含むアーカイバを適用します。



TimeTracker.zip(194 Kb)

bg.png* .9.pngicon.png 、およびtopshadow.pngファイルを展開して、 ドロアブルディレクトリにスローします。

9.pngは9パッチのドロアブルです。 それについての詳細はdeveloper.android.com/guide/developing/tools/draw9patch.htmlで読むことができます。これらのファイルには必要に応じて画像の特定の部分のみを伸ばす機能があることに注意してください。 ボタンはこのように機能します。 コンテンツテキストが元の画像よりも大きい場合、またはボタンにlayout_width / height = fill_parent属性がある場合、Androidはビットマップ全体ではなく、マークされたセクションのみを拡大します。



私がそれを始めたとき、私はそれを考慮しませんでしたが、将来、これらの画像は最小の長さと幅を持つ必要があることに気づくでしょう、私は100ピクセルの幅を持っているので、私は100ピクセルのボタンをしません。



次に、背景画像、ヘッダーを拡大し、ボタンの状態から写真を変更する方法をアンドロイドに知らせる必要があります。

これを行うには、drawableフォルダーにファイルbackground.xml、greebutton.xml、redbutton.xml、およびheader.xmlを作成します。



最初のファイルには次のように記述します。

 <ビットマップxmlns:android = "http://schemas.android.com/apk/res/android"
 android:src = "@ drawable / bg"
 android:tileMode = "repeat" />



srcは、ビットマップへのパス、つまりbg.pngファイルへのパスです。bg.pngファイルは、描画可能なフォルダーにあります。

tileMode-表面を正しく描画する方法。



greenbutton.xmlの場合:

 <?xml version = "1.0" encoding = "utf-8"?#62;
 <selector xmlns:android = "http://schemas.android.com/apk/res/android">
	 <item android:state_pressed = "true"
		 android:drawable = "@ drawable / greenbutton_dark" /> <!-押された->
	 <item android:state_focused = "true"
		 android:drawable = "@ drawable / greenbutton_dark" /> <!-フォーカス->
	 <item android:drawable = "@ drawable / greenbutton_light" /> <!-デフォルト->
  </ selector>



ボタンの状態ごとにビットマップを指定します。 たとえば、フォーカス状態の画像を追加できます。



redbutton.xmlの場合、ビットマップを除き、すべてはgreenbutton.xmlと同じです。 ハブラーでは、人々は賢いので、そこに何を書く必要があるかを理解できると思います。

header.xmlの場合、すべてはbackground.xmlと同じですが、ビットマップが異なります。



レイアウトフォルダに移動します。アプレットインターフェイスを記述するxmlファイルがあります。

私たちの場合、単一のファイルがあり、それを開いて次の形式にします。

 <?xml version = "1.0" encoding = "utf-8"?>
 <RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     android:orientation = "vertical"
     android:layout_width = "fill_parent"
     android:layout_height = "fill_parent"
     android:background = "@ drawable / background"
     >
 </ RelativeLayout>


RelativeLayoutを使用すると、自分自身または互いに対して要素を配置できます。 これにより、ヘッダーにタイマーを設定できます。

次のオプションについて説明しました。

方向 -このレイアウトの子の方向。

たとえば、LinearLayoutにorientation = "vertical"パラメーターを使用して2つのボタンを配置すると、2つのボタンは互いの下に、orientation = "horizo​​ntal"パラメーターを使用して次々に配置されます。

layout_widthとlayout_height-幅と高さ。 3つのタイプの値が受け入れられます:fill_parent(親パラメーターを受け入れる)、wrap_content(コンテンツが切り捨てられない最小値)、または数値。

背景 -背景。 もう少し上に、drawableフォルダーにbackground.xmlを作成したので、今すぐアクセスしています。

「@ <resフォルダ内のフォルダ> / <このフォルダ内のファイル>」と説明します。 識別子は同じ方法で設定されますが、それについては後で詳しく説明します。

次に、RelativeLayout内で、さらに3つの要素を作成します。

Imageview

 <ImageView
	 android:src = "@ drawable / header"
	 android:layout_width = "fill_parent"
	 android:layout_height = "100px"
	 android:scaleType = "fitXY"
	 android:layout_alignParentTop = "true"
 />


srcは、アプレットの上部にあるシャドウのパラメーターを含む、最近作成したheader.xmlへのパスです。

scaleType-ストレッチ方法。

原則として、header.xmlを使用せずに、topshadow.pngへのパスをすぐに指定できます。

layout_alignParentTop-各RelativeView子にはこのタイプのパラメーターがあり、要素を配置する場所を示します。 具体的には、親の上部の境界、つまりRelativeViewに描画する必要があることを示唆しています。



タイマー付きリニアレイアウト

 <LinearLayout
	 android:orientation = "vertical"
	 android:layout_width = "fill_parent"
	 android:layout_height = "200dip"
	 android:layout_centerVertical = "true"
	 android:layout_centerInParent = "true"
 >
	 <TextView
		 android:text = "00:00:00"
		 android:id = "@ + id / rest_timer"
		 android:textColor = "#AAFFAA"
		 android:textSize = "40dip"
		 android:gravity = "center_horizo​​ntal | bottom"
		 android:singleLine = "true"
		 android:layout_width = "fill_parent"
		 android:layout_height = "80dip"
	 />
	 <TextView
		 android:text = "00:00:00"
		 android:id = "@ + id / work_timer"
		 android:textColor = "#FFAAAA"
		 android:textSize = "40dip"
		 android:gravity = "center_horizo​​ntal | top"
		 android:singleLine = "true"
		 android:layout_width = "fill_parent"
		 android:layout_height = "80dip"
	 />
 </ LinearLayout>


id-ウィジェット識別子。 新しい識別子を作成するには、「@ + id / <name>」を使用して既存の識別子にアクセスします。たとえば、設定で別のアイテム「@ id / <name>」の選択に依存する必要があります。

textColor-テキストの色。 #RRGGBBまたは#AARRGGBBのいずれかに設定されます。AAは16進アルファチャネル(透明度)、RR、GG、およびBBは各色の16進です。

singleLine -1行のテキスト。

gravity-テキスト自体の配置。

テキスト -XDを自分で推測してみてください。



ボタン付きのLinearLayout

 <LinearLayout
	 android:layout_alignParentBottom = "true"
	 android:layout_width = "fill_parent"
	 android:layout_height = "wrap_content"
	 android:orientation = "horizo​​ntal"
	 >
	 <ボタン
		 android:id = "@ + id / rest"
		 android:layout_weight = "1"
		 android:text = "@ string / button_rest"
		 android:textSize = "18dip"
		 android:textColor = "#FFFFFF"
		 android:textStyle = "bold"
		 android:layout_height = "wrap_content"
		 android:layout_width = "fill_parent"
		 android:background = "@ drawable / greenbutton"
		 />
	 <ボタン
		 android:id = "@ + id / work"
		 android:layout_weight = "1"
		 android:text = "@ string / button_work"
		 android:textSize = "18dip"
		 android:textColor = "#FFFFFF"
		 android:textStyle = "bold"
		 android:layout_height = "wrap_content"
		 android:layout_width = "fill_parent"
		 android:background = "@ drawable / redbutton"
		
		 />	
 </ LinearLayout>


ここではすべてが原則として明確です。 テキストは文字列としてでなく、行を含むファイル内の行へのリンクとして設定されていることに注意してください...いくつかのタフタロジー...これについてはもう少し書いて、そのままにしておきます



アニメーション



原則はこれです。 ボタンを押すと、1つのタイマーが減少し、別のタイマーが増加します。

resフォルダーにanimサブフォルダーを作成します。 そこで、4つのxmlファイルを示します:magnify_rest.xml、shrink_rest.xml、magnify_work.xml、shrink_work.xml。

magnify-タイマーを増やします。

縮小 -タイマーを減らします。



magnify_rest.xmlを開きます。

 <?xml version = "1.0" encoding = "utf-8"?>
 <scale xmlns:android = "http://schemas.android.com/apk/res/android"
	 android:fromXScale = "1.0"
	 android:toXScale = "2.0"
	 android:fromYScale = "1.0"
	 android:toYScale = "2.0"
	 android:pivotX = "50%"
	 android:pivotY = "100%"
	 android:startOffset = "0"
	 android:duration = "400"
 />


fromXScaleとfromYScaleは、アニメーションの開始前の寸法です。 2.0を入力すると、テキストは最初は急激に2倍になり、既にこの値からサイズが変更されます。

toXScaleとtoYScaleは、アニメーションの最後のサイズ値です。 2.0を使用しています。つまり、テキストのサイズは、fromXScaleおよびfromYScaleではなく、レイアウトで指定された元の値の2倍になります。

ピボットXとピボットYは、アニメーションの元になるポイントです。 たとえば、両方を50%に設定すると、テキストはすべての方向に増加し、pivotX = 0%にすると、テキストは右に、100%に左に増加します。

startOffset-アニメーションの開始前の間隔。

duration-ミリ秒単位のアニメーション時間。



shrink_rest.xml:

 <?xml version = "1.0" encoding = "utf-8"?>
 <scale xmlns:android = "http://schemas.android.com/apk/res/android"
	 android:fromXScale = "2.0"
	 android:toXScale = "1.0"
	 android:fromYScale = "2.0"
	 android:toYScale = "1.0"
	 android:pivotX = "50%"
	 android:pivotY = "100%"
	 android:startOffset = "0"
	 android:duration = "400"
 />


ここでは、サイズを除いてすべて同じです。



その結果、私は取得したい:







親の垂直方向の中央に揃えられた2つのタイマー。 ボタンを押すと、上のボタンが上がり、下のボタンも上がります。 私は別のボタンを押すと、それらはそれに応じて減少および増加します。 これらはすべて、互いにぶつからないように行われます。

したがって、上部の2つのピボットは下部の中心点として示されます。 他の2つのファイルでは、すべてが同じです。ただし、ピボットは既に最上部の中心点、つまり50%と0%を指している点が異なります。



文字列とローカライズ



res / values / strings.xmlに移動して、次の形式にします。

 <?xml version = "1.0" encoding = "utf-8"?>
 <リソース>
     <string name = "hello"> Hello World、Main!</ string>
     <string name = "app_name">タイムマネージャー</ string>
    
     <string name = "button_work">作業</ string>
     <string name = "button_rest">残り</ string>
 </ resources>


name-少し前に私がこれについて言及したので、 文字列 / helloコンストラクトはHello World、Main!

このファイルには、プログラムで使用するすべての行が含まれています。



ローカライズのために、values- <local>ディレクトリ、この場合はvalues-ruを作成し、そこにstrings.xmlファイルをコピーし、それを開いて、ストリング値をロシア語に翻訳します。



プログラム



小さい場合。 プログラム自体を作成して、このすべての美しさが動揺し、どもり、引き締められるようにします。

srcフォルダーのjavaファイルを開きます。 彼は一人でそこにいるべきです。

一番上に名前のパッケージがあり、私の場合はcom.nixan.timetrackerです。

次に、他のクラスのインポートがあります。

次に、クラス自体の宣言:



パブリッククラスMainはActivityを拡張します



Mainの代わりに、プロジェクトを作成するときにcreateアクティビティで設定したものなど、何か他のものがある場合があります。

アクティビティは... Windowsでのフォームの類似物です。 ListActivity-再カウントするいくつかの要素のリスト、PreferenceActivity-設定を含むウィンドウもあります。これらはすべて個別のxmlファイルで定義されており、このすべての美しさのためにレイアウトを作成する必要はありませんが、これはそれについてではありません。

このクラスには、ウィンドウの作成時に呼び出されるonCreate()メソッドがあります。 そのような方法がいくつかあります。詳細については、 developer.android.com / guide / topics / fundamentals.html#actlifeを参照してください。



onCreateの前に、変数を設定します。

ボタンrest_button;
ボタンwork_button;
 TextView rest_timer;
 TextView work_timer;
アニメーションmagnify_rest;
アニメーションshrink_rest;
アニメーションmagnify_work;
アニメーションshrink_work;
 TimerTaskカウンター。
タイマータイマー
ブール休憩;
ブール作業;
 int rest_time;
 int work_time;
 SharedPreferences.Editor stats_editor;


rest_buttonおよびwork_button-仕事/休憩を切り替えるためのボタン。

rest_timerおよびwork_timer-現在のタイマー値を表示するテキスト。

magnify_rest、shrink_rest、magnify_work、shrink_workは、xmlファイルで設定したアニメーションです。

counterはタイマーが行うことです。

タイマー -タイマー自体。

休息と作業は、現在の状態が保存される変数です。

rest_timeおよびwork_time-実際には何秒が働いて休んだか。

stats_editor-設定、費やされた秒、休憩された秒はそれらに保存され、プログラムを閉じてもタイマーはリセットされません。



さあ、行こう!



まず、親のonCreateの呼び出しがあるかどうかを確認します。

 super.onCreate(savedInstanceState);


そうでない場合は、追加します。



次に、このアクティビティにどのレイアウトを描画するかを伝えます。

 setContentView(R.layout.main);


R.layout.mainは「@ layout / main」に類似しています。mainはレイアウトフォルダーのmain.xmlです。 レイアウトがメインと呼ばれない場合、呼び出しを修正します。

setContentView()の前; requestWindowFeature();を追加することもできます。これは、たとえばWindow.FEATURE_NO_TITLEなどのパラメーターで渡すことができ、ウィンドウ上部の灰色のタイトルを削除します。



保存されたタイマーパラメーターを取得します。

 SharedPreferences saved_stats = PreferenceManager.getDefaultSharedPreferences(this);
 rest_time = saved_stats.getInt( "key_rest_time"、0);
 work_time = saved_stats.getInt( "key_work_time"、0);


getInt -2つのパラメーターがメソッドに渡されます。パラメーターの名前を示すストリングと、ストリングが見つからない場合のデフォルトのパラメーターです。



変数を初期化します。

 stats_editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
 magnify_rest = AnimationUtils.loadAnimation(this、R.anim.magnify_rest);
 shrink_rest = AnimationUtils.loadAnimation(これ、R.anim.shrink_rest);
 magnify_work = AnimationUtils.loadAnimation(this、R.anim.magnify_work);
 shrink_work = AnimationUtils.loadAnimation(this、R.anim.shrink_work);
 resting = false;
 working = false;
 rest_timer =(TextView)findViewById(R.id.rest_timer);
 work_timer =(TextView)findViewById(R.id.work_timer);
 rest_button =(ボタン)findViewById(R.id.rest);
 work_button =(ボタン)findViewById(R.id.work);




私の場合、2つの異なる方法で秒から文字列HH:MM:SSへの変換を行いました。

悪いJavaを前もってすみませんが、最初の人はより少ないメモリを消費しますが、動作が遅くなり、逆もまた同様です。

 private String getTime(int time)
	 {
		文字列の結果= "";
		 int時間=時間/ 3600;
		 int minutes =(時間-(時間* 3600))/ 60;
		 int seconds =(時間-(時間* 3600)-(分* 60));
		 result = String.valueOf(時間)+ ":";
		 if(分<10)
		 {
			 result + = "0" + String.valueOf(分)+ ":";
		 }
		他に
		 {
			結果+ = String.valueOf(分)+ ":";
		 }
		 if(秒<10)
		 {
			 result + = "0" + String.valueOf(秒);
		 }
		他に
		 {
			結果+ = String.valueOf(秒);
		 }
		結果を返す;
	 }


もう一度言いますが、どれだけ正確で有能かはわかりませんが、うまくいくようです。



そして、変数が初期化された直後に、次を追加します。

 rest_timer.setText(getTime(rest_time));
 work_timer.setText(getTime(work_time));


したがって、以前に計算された秒をタイマーのテキストに設定します。



タイマーのタスクを作成します。

カウンター=新しいTimerTask()
	 {
		 @Override
		 public void run(){
		 }
	 };




タイマーの秒、分、時間を担当する変数をオーバーライドする前。 プロセス全体が1つのタイマーで実装されるため、休息と作業のセットは次のようになります。

 int seconds_r = 0;
 int hours_r = 0;
 int minutes_r = 0;
文字列seconds_ind_r;
文字列minutes_ind_r;
文字列hours_ind_r;
 int seconds_w = 0;
 int hours_w = 0;
 int minutes_w = 0;
文字列seconds_ind_w;
文字列minutes_ind_w;
文字列hours_ind_w;




そして実際にはアカウントのタスク:

 if(休息)
	 {
		 if(seconds_r == 0 && minutes_r == 0 && hours_r == 0)
		 {
			 hours_r = rest_time / 3600;
			 minutes_r =(rest_time-(hours_r * 3600))/ 60;
			 seconds_r =(rest_time-(hours_r * 3600)-(minutes_r * 60));							
		 }
		 rest_time ++;
		 seconds_r ++;
		 if(seconds_r> = 60)
		 {
			 seconds_r = 0;
			 minutes_r ++;
			 if(minutes_r> = 60)
			 {
				 minutes_r = 0;
				 hours_r ++;
			 }
		 }
		 if(seconds_r <10)
		 {
			 seconds_ind_r = "0" + String.valueOf(seconds_r);
		 }
		他に
		 {
			 seconds_ind_r = String.valueOf(seconds_r);
		 }
		 if(minutes_r <10)
		 {
			 minutes_ind_r = "0" + String.valueOf(minutes_r);
		 }
		他に
		 {
			 minutes_ind_r = String.valueOf(minutes_r);
		 }
		 hours_ind_r = String.valueOf(hours_r);
		 runOnUiThread(新しいRunnable()
		 {
			 public void run(){
			 // TODO自動生成メソッドスタブ
			 rest_timer.setText(hours_ind_r + ":" + minutes_ind_r + ":" + seconds_ind_r);
			 }
		 });  
	 }


restingは、 休憩中であることを示すブール変数です。

runOnUiThread() -インターフェースを使用してスレッド内のコードを実行します。

上記の残りのコードは仕事用で、その直後に、同様のコードが追加されます。仕事用の秒、分、時間のセットのみがあり、最初のifはif(working)に変更され、rest_timerではなくwork_timerにテキストを設定します'a。



ポイントは小さい:キーストロークを処理します。

 rest_button.setOnClickListener(新しいOnClickListener()
	 {
		 public void onClick(View v){
		 if(!休憩)
		 {
			 rest_timer.startAnimation(magnify_rest);
			 resting = true;
		 }
		他に
		 {
			 rest_timer.startAnimation(shrink_rest);
			 resting = false;
			 stats_editor.putInt( "key_rest_time"、rest_time);
		 }
		 if(作業中)
		 {
			 work_timer.startAnimation(shrink_work);
			 working = false;
			 stats_editor.putInt( "key_work_time"、work_time);
		 }
	 stats_editor.commit();
	 }
 });       


現時点で休んでいない場合は、休み始めます。

休むと休みが止まります

動作する場合、動作を停止します。

この場合、動作中および休止中の論理変数のみが変更され、タイマーで毎秒チェックされ、それらがオンになっている場合、時間が増加し始めます。



したがって、ボタンを2回押すと、通常、動作モードを含めずにタイマーをオフにできます。



作業ボタンについては、すべてが似ています。



保存しながら、ハンドセットを接続してアプリケーションを起動します。



そしてすぐに最初のバグを見つけました。 タイマーが実行されているときに画面を回転させると、タイマーは停止します。



私たちは見つけます:

 resting = false;
 working = false;




そして次のように変更します:

 resting = saved_stats.getBoolean( "key_resting"、false);
 working = saved_stats.getBoolean( "key_working"、false);
 if(休息)
 {
	 rest_timer.startAnimation(magnify_rest);
 }
 if(作業中)
 {
	 work_timer.startAnimation(magnify_work);
 }




各ハンドラーでは、ボタンをクリックします。

 stats_editor.commit();




それに追加します:

 stats_editor.putBoolean( "key_working"、working);
 stats_editor.putBoolean( "key_resting"、休憩);


つまり、フォームをレンダリングするときに、ボタンが押されたときに保存されたキーの値を受け取ります。



実行、突く、すべてが大丈夫のようです。



脅威

それだけの価値があれば、アプレットがメモリにハングアップし、常に実行し続ける必要がないように、少し後でサービスの記述を続けます。

ZYY

ソース(誰かが興味を持っている場合) -nixan.org/habr/timetracker/TimeManager.zip

ZYYY

nixan.org/habr/timetracker/TimeManager.apk-プログラムを含むパッケージ、またはパブ市場:Nixan

ZYYYY

ビデオを追加しました。

ZYYYYY

Android用のシンプルタイムマネージャー。 パート2



All Articles