最初からAndroidコンポーネント

みなさんこんにちは! 多くの場合、同様のプログラムの一般的な塊から目立つためには、独自のインターフェイスコンポーネントを作成する必要があります。 この記事では、タイマーボタンを例として使用して、単純な非標準コンポーネントを作成する方法について説明します。



割り当て:


次のように機能するスライダーボタンを開発します。左側の長方形の領域は、シフトの方向を示す矢印の付いたブロックです。



ユーザーは矢印を固定し、右に移動します。矢印が格納されると、矢印は色付きの正方形を描きます。



ユーザーがブロックを解放するとすぐに、行全体が左に移動し、表示されているすべてのブロックが非表示になります。 最後のブロックを非表示にすると、テープが完全に非表示になったというブロードキャストメッセージが生成されます。



準備する


新しいコンポーネントを作成するには、新しいプロジェクトを作成します。 次に、「CustomButton」という名前の新しいクラスを作成し、「View」クラスを祖先として使用します。 次に、クラスコンストラクターを作成します。その結果、将来のコンポーネントは次のようになります。

package com.racckat.test_coponent; import android.content.Context; import android.util.AttributeSet; import android.view.View; public class CustomButton extends View { public CustomButton(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } }
      
      





次に、クラスコードの記述を開始します。 コードを書き始める前に、カラフルなテープのイメージである/ res / drawable-hdpiフォルダーにドロップします。 コンストラクターでは、最初にすべてのオブジェクトを初期化し、すべてのプリセットを作成する必要があります。 次のことを行います。

1-リンクをメインアクティビティのコンテキストにコピーします。

2-準備されたブランクストリップを色付きの正方形で分割してロードします。

3-表面に描画するために必要なコンポーネントを構成します/

 public CustomButton(Context context, AttributeSet attrs) { super(context, attrs); _Context = context; //   //   _BMP_line = BitmapFactory.decodeResource(getResources(),R.drawable.line); //   mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(16); mPaint.setColor(0xFFFFFFFF); mPaint.setStyle(Style.FILL); }
      
      





また、クラスの先頭でオブジェクトを宣言します。

  private Paint mPaint; //   public Bitmap _BMP_line; //   Context _Context; // 
      
      





次に、コンポーネントのサイズ変更手順-onMeasureを再定義する必要があります。 例が複雑にならないように、コンポーネントの一定の寸法(300 * 50)を具体的に作成しました。 手順は次のようになります。

  @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(300, 50); }
      
      





ここで、「onDraw」コンポーネントを再描画する手順を再定義します。 このプロシージャは、コンポーネントを再描画する必要があるたびに呼び出されます。 手順は次のようになります。

  @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0,0, 300, 50, mPaint); canvas.drawBitmap(_BMP_line, 0, 0,null); }
      
      





新しいコンポーネントのブランクの準備ができました。メインアクティビティに追加しましょう。 まず、メインサーフェスに「LinearLayout1」という名前で新しいLinearLayoutを配置します。 次に、クラスコンストラクターで、新しいボタンのクラスを作成し、実装クラス「LinearLayout1」を作成して、ボタンをサーフェスに追加します。 アクティビティクラスは次のようになります。

 package com.racckat.test_coponent; import android.os.Bundle; import android.annotation.SuppressLint; import android.app.Activity; import android.widget.LinearLayout; public class MainActivity extends Activity { @SuppressLint("WrongCall") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LinearLayout _LL1 = (LinearLayout) findViewById(R.id.LinearLayout1); CustomButton _CB1 = new CustomButton(MainActivity.this, null); _LL1.addView(_CB1); } }
      
      





実行時にプロジェクトを実行すると、デバイス(エミュレーター)に次のようなものが表示されます。





機能的


次に、アニメーションと外部イベントへの反応の実装を開始します。 ユーザーが祖先がViewであるインターフェイスのコンポーネントをクリックすると、イベントが自動的に生成されます。特に、コンポーネントをクリックした座標とクリックの段階(クリック、移動、押下)を追跡できます。 したがって、外部イベントを処理するonTouchEventプロシージャをオーバーライドする必要があります。 プロシージャには「MotionEventイベント」という引数が1つあり、現在のイベントのすべてのパラメーターが含まれています。 これらのパラメーターを次のように抽出します。

  Float X=(Float)event.getX(); //   X Float Y=(Float)event.getY(); //   Y int Action=event.getAction(); // 
      
      





手順を次のフォームに記載します。

  @Override public boolean onTouchEvent(MotionEvent event) { //    Float X=(Float)event.getX(); //   X Float Y=(Float)event.getY(); //   Y int Action=event.getAction(); //  if((Action==MotionEvent.ACTION_DOWN)&&(X<60)&&(_Last_Action==0)) { _Last_Action = 1; //  _X = 0; } if((Action==MotionEvent.ACTION_MOVE)&&(_Last_Action == 1)) { _X = (int) (X/60); if (_X>4) _X=4; //     ,    if (_X<0) _X=0; invalidate(); //    } if (Action==MotionEvent.ACTION_UP){ _Last_Action = 2; if (_X>0) MyTimer(); //   else _Last_Action = 0; } return true; }
      
      





各行をペイントするのではなく、主なアイデアのみを決定します。 ユーザーがコンポーネントの矢印をクリックすると、このアクションは変数_Last_Action = 1に固定されます。また、ユーザーがテープからサイコロを引いていないことも修正します-_X = 0。 。 再描画は、invalidate()コマンドを使用して行われます。 最後に、ユーザーが少なくとも1つのダイを引いた場合、フィンガーリリースを修正し、タイマーを開始します。 ストリップを元の状態に鋭くではなく徐々に戻すには、タイマーが必要です。



ここで、タイマー自体を実装します。これにより、ストリップが元の位置に戻ります。 タイマーコードは次のようになります。

  //   public void MyTimer(){ Thread t = new Thread(new Runnable() { public void run() { for(;;){ try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) {e.printStackTrace();} _X--; myHandler.sendEmptyMessage(0); if (_X==0){//      myHandler.sendEmptyMessage(0); //   _Last_Action = 0; //     break; //    } } } }); t.start(); }
      
      





この手順では、変数_Xの値を1減らす操作は周期的であるため、コンポーネントに表示するセクターを示します。 追加のスレッドからコンポーネントの外観に影響を与えることはできないため、Handleを使用して再描画メッセージを送信する必要があります。 したがって、クラスコンストラクターで、Handleのメッセージインターセプトの実装を追加し、ウィジェットの外観を再描画します。

  myHandler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what==0){ invalidate(); //    } } };
      
      





ウィジェットを再描画する手順、つまり、リボンを表面に配置するための線(リボン上の1つの正方形の幅は60ピクセル、全長は300ピクセル)を変更する必要があります。

 canvas.drawBitmap(_BMP_line, (_X*60)-240, 0,null);
      
      





すべての変数をクラス実装の先頭に追加します。

その結果、クラスは次のようになります。

 package com.racckat.test_coponent; import java.util.concurrent.TimeUnit; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.os.Handler; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; public class CustomButton2 extends View { private Paint mPaint; //   public Bitmap _BMP_line; //   int _Last_Action; //      int _X = 0; //     public Handler myHandler; //      Context _Context; //  public CustomButton(Context context, AttributeSet attrs) { super(context, attrs); _Context = context; //   //   _BMP_line = BitmapFactory.decodeResource(getResources(),R.drawable.line); //   mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setTextSize(16); mPaint.setColor(0xFFFFFFFF); mPaint.setStyle(Style.FILL); myHandler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what==0){ invalidate(); //    } } }; } @Override public boolean onTouchEvent(MotionEvent event) { //    Float X=(Float)event.getX(); //   X Float Y=(Float)event.getY(); //   Y int Action=event.getAction(); //  if((Action==MotionEvent.ACTION_DOWN)&&(X<60)&&(_Last_Action==0)) { _Last_Action = 1; //  _X = 0; } if((Action==MotionEvent.ACTION_MOVE)&&(_Last_Action == 1)) { _X = (int) (X/60); if (_X>4) _X=4; //     ,    if (_X<0) _X=0; invalidate(); //    } if (Action==MotionEvent.ACTION_UP){ _Last_Action = 2; if (_X>0) MyTimer(); //   else _Last_Action = 0; } return true; } //   public void MyTimer(){ Thread t = new Thread(new Runnable() { public void run() { for(;;){ try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) {e.printStackTrace();} _X--; myHandler.sendEmptyMessage(0); if (_X==0){//      myHandler.sendEmptyMessage(0); //   _Last_Action = 0; //     break; //    } } } }); t.start(); } @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(300, 50); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawRect(0,0, 300, 50, mPaint); canvas.drawBitmap(_BMP_line, (_X*60)-240, 0,null); } }
      
      







外部メッセージ


私たちはあまり賢くありません。ブロードキャストメッセージの助けを借りて、「テープが隠されている」というイベントを実感しています。 タイマーの実装で、メッセージ送信行を追加します。

  //    Intent intent1 = new Intent("com.anprog.develop.timer_button_alarm"); intent1.putExtra(Name, 1); _Context.sendBroadcast(intent1); //   
      
      





変数「Name」には、コンポーネントの名前が格納されます。 名前を保存するには、追加の手順を作成します。

 public void SetName(String _name){ Name = _name; }
      
      





コンポーネント名-public String Nameをオブジェクト宣言ブロックに追加します。

アクティビティのコンストラクターで、ブロードキャストインターセプターを追加します。

 //   BroadcastReceiver _br = new BroadcastReceiver() { //     @Override public void onReceive(Context arg0, Intent intent) { int status_alarm_line_button_1 = intent.getIntExtra("line_button_1", 0); if (status_alarm_line_button_1==1) { //     Toast toast = Toast.makeText(getApplicationContext(),"Line alarm!!!", Toast.LENGTH_SHORT); toast.show(); } } }; registerReceiver(_br, new IntentFilter("com.anprog.develop.timer_button_alarm"));
      
      





ボタンオブジェクトを作成するための行の後に、新しい名前をオブジェクトに渡すための行を追加します。

 _CB1.SetName("line_button_1"); //   
      
      





標準コンポーネントではなく、すべての準備が整ったら、テストを開始してください

理想的になるはずです-http://youtu.be/3iGxOlWHB0w

次のリンクですべてのコメント付きのサンプルアーカイブをダウンロードできます-http://www.anprog.com/documents/Line_timer.zip



All Articles