Androidの開発では、我々は単独の制御システムが提供したときに、いくつかの特別な制御を使用する必要がある場合、当社のUIコントロールは、限られているために、システムが提供する、私たちが望む結果を達成しないかもしれない、そして、我々は自己を必要としますいくつかのコントロールの定義は、私たちが望む効果を完了します。今、私はそれらの事カスタムコントロールについて何かを言うだろう。
まず第一に、私は、Androidの制御アーキテクチャについて何かを言います。Androidのコントロールは、2つのカテゴリ、すなわちに分けることができるのViewGroupと見ます。ViewGroupには複数のビューが含まれており、それらを管理することができます。コントロールツリーは、コントロールツリーをプロットし、基本的な制御との相互作用を測定しているため二部上層が担当して持つことです。我々はfindViewByIdアクティビティ()メソッド内のIDに対応するツリートラバーサル検索深さの制御方法で使用される使用します。一人一人が木の上を制御し、木全体の中核ですViewParentオブジェクトが存在する、すべての対話イベントをスケジュールする責任があります。活動では、レイアウトをロードするためにsetContentView()を使用しています。各アクティビティが含まれているWindowオブジェクトアンドロイドでは通常PhoneWindowで、彼はなりますDecorViewルートがウィンドウ全体を見ると、コンテンツが表示窓に表示されます。DecorViewは1つがあり、2つの部分に分割されるtitleview、あるContentView。ContentViewがでframeLayoutのコンテンツのIDであり、この文書のレイアウトは、内部を設定することです。そしてTitleViewは、我々はtopbarタイトルバーを見たものです。これは、活動のプロセスは、レイアウトファイルをロードしています。
次に、我々はピンチの原則のいくつかを分析すると、以下の説明を使用して、カスタムコントロールの使用について話し始めました。カスタムコントロールは、一つには、それらの所望の効果を達成するために、Googleが提供する制御システムの拡張であり、三種類に分けることができます。一つは、対照組成物として使用される複合制御システムを提供することです。コントロールの再描画新しいメジャーもあります。
まず、制御システムの拡張は、Googleが提供しています
我々はTextViewの制御に拡張したい場合は、私たちはクラスを定義する必要があり、そのonDraw()、onMeasure()、onTouchEvent()メソッドを書き換える選択、TextViewに継承しています。画像をレンダリングするための責任がある、onDraw()、onMeasureは()(、onTouchEvent位置を測定するための責任がある)タッチイベントを設定するための責任があります。私たちは直接のTextViewの背景色をマップしたい場合は、ブラシは、onDraw()を描くために、クラスで定義することができます。コードは以下の通りであります:
=新しいペイントをpaint1ペイント(); //定义画笔 paint1.setColor(Color.YELLOW)。 paint1.setStyle(Paint.Style.FILL)。
その後、次のコードは、あなたが四角形でのTextViewを描くことができますが、それは、システムのコントロールに拡大しているため、コールonDraw親クラス()の完了時に描画する必要があるので、また本来の機能を持っています。
@Overrideは ボイドonDraw(キャンバスキャンバス){保護 //绘制矩形、canvas.drawRect(0,0、getMeasuredWidth()、getMeasuredHeight()、paint1) canvas.saveを(); super.onDraw(キャンバス)。 canvas.restore(); }
キャンバスに説明し、描画することができキャンバスオブジェクトを使用して、私は次のブログ記事で説明します。
その後、我々は唯一の自己定義されたビュー名は、それがCustomTextviewクラスの継承のTextViewを定義すると仮定すると、クラス名とパッケージ名のカスタムクラスで、レイアウトファイルでカスタマイズすることができ、レイアウトファイルにコントロールを追加する必要があり、次のように、例を示します。
<com.example.myapplication.View.CustomTextViewの アンドロイド:layout_width = "wrap_content" のandroid:layout_height = "match_parent"> </ com.example.myapplication.View.Buttonbtn>
第二に、制御システムは、組み合わさ提供します
既存のコントロールを拡張することに加えて、我々はまた、新たな制御用にまとめることができます制御します。まずは、新しいレイアウトファイルを定義してみましょうし、次のようにImageViewのとTextViewには、追加。
<ImageViewの アンドロイド:ID = "@ + ID / IV" のandroid:layout_width = "20dp" のandroid:layout_height = "20dp" アンドロイド:SRC = "@ミップマップ/ ic_launcher" /> <TextViewには アンドロイド:ID = "@ + ID /テレビ」 アンドロイド:layout_width = "wrap_content" のandroid:layout_height = "wrap_content" アンドロイド:layout_marginTop = "2DP" アンドロイド:テキスト= "消息" アンドロイド:TEXTSIZEは= "13sp" />
その後、我々はのLinearLayoutを継承するクラスを定義し、コントロールのレイアウトは、コンストラクタクラスで初期化されます。
INIT公開(コンテキスト・コンテキスト){無効 //指定された線形レイアウトを表示する、垂直 setOrientation(VERTICAL); //設定されたユーザの所望のレイアウト LayoutParams mLayoutParams =新しいLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT、 ViewGroup.LayoutParams.WRAP_CONTENT)。 setLayoutParams(mLayoutParams); setGravity(Gravity.CENTER); setPadding(4 ,. 4 ,. 4 ,. 4。); //そのレイアウトファイルセット ビューmButtonbtnView = LayoutInflater.from(コンテキスト).inflate (layout.botton_btn_view、この、真の); = mButtonbtnView.findViewById mImageView(id.iv); mTextView = mButtonbtnView.findViewById(id.tv); }
次に、その使用が拡大し、その制御方法、直接レイアウトファイルには、コントロールが可能追加されます。
<com.example.myapplication.View.Buttonbtnの
アンドロイド:layout_width = " wrap_content "
のandroid:layout_height =" match_parent"> </ com.example.myapplication.View.Buttonbtn>
第三に、新しいコントロールを実装するには、[View]を書き換えます
システムネイティブコントロールは、私たちの要求を満たしていない場合は、我々は必要な機能を完了するために、新しいコントロールを定義することができます。あなたはViewクラスを継承する必要があり、新しいコントロールを作成し、その主な問題は、コントロールを描画し、対話することにあります。Viewクラスを継承した際に、我々はまた、ドロー、測定、およびタッチイベントを達成するために、そのonDraw()を、onMeasure()、onTouchEvent()書き換える必要があります。
形状制御のための描画キャンバスオブジェクトに描画する方法の一連の呼び出しonDraw()。
onMeasure()
今、私は()onMeasureについて何かを言います。ビューを描画する前に、我々は我々がonMeasureで彼の位置、だけでなく、ビューを描画する必要がどのくらいのシステムに伝える必要があります()を実施。まずは、測定の三つのモードを見てみましょう:
EXACTLY:正確な値モードビューを指定する場合、具体的な数値が使用されます。
AT_MOST:マックスモード、コントロールが設定されている「wrap_content」が使用され、それが子コントロールやコンテンツの変更によって異なります。
UNSPECIFIED:あなたは大きなになりたいどのくらいのコントロールを描画します。
上記の3つのモードによると、我々は判断することができ、測定時に使用します。まず第一に、我々は()メソッドのonMeasureビューを書き換えます。次いで、制御は、測定モードMeasureSpecクラスを使用することによって得られます。MeasureSpec高い測定モード2、残りの30は、測定サイズであるビット演算を使用。
@Override 保護ボイドonMeasureを(INT widthMeasureSpec、INT heightMeasureSpec){ int型widthMode = MeasureSpec.getMode(widthMeasureSpec)。 INT widthSize = MeasureSpec.getSize(widthMeasureSpec)。 {(widthMode == MeasureSpec.EXACTLY)もし }そうであれば(widthMode == MeasureSpec.AT_MOST){ }そうであれば(widthMode == MeasureSpec.UNSPECIFIED){ } }
このコードは、ここで測定され、コントロールを定義するパターンのサイズを測定することによって決定される制御の幅であり、測定の高さは同様で制御し、説明しません。
前述したように、のViewGroupがコントロールを管理するために使用されるのViewGroupの大きさである場合には、とき「wrap_content」、それは再び自身のサイズを設定し、子ビューのサイズを取得するには、そのサブビューのすべてを横断します。RelativeLayout、のLinearLayoutのViewGroupが継承されるように我々は、レイアウトを使用するので、彼らはまた、独自のサイズを取得するには、このメソッドを使用します。
onTouchEvent()
Android携帯は画面をタッチすると、その私たちのカスタムビュータッチスクリーンですが、また相互作用を完了するために、いくつかのプロセスを持っている必要があるためonTouchEvent()は、私たちはタッチイベントと呼んでいます。onTouchEventメソッドを書き換える場合、我々は、オブジェクトがMotionEventを渡す必要があることがわかります。私たちはあなたのタッチポイントの位置を取得することができ、このクラスを介してタッチイベントを設定することができます。私たちは、画面を押すか、移動しているかどうかを判断するためにgetAction()、によるアクションのタッチイベントを取得することができます。Androidの座標系では、我々はすべての肖像画でAndroidの画面は、それが原点と左上隅に来るときことを知って、右方向はこのポストを知って、正のx軸、y軸正方向下向きです、我々はいくつかの相互作用を完了することのgetX()とのgetY()メソッドを呼び出すことによって、タッチポイントの座標を取得することができます。
パブリックブールonTouchEvent(MotionEventイベント){ フロートX。 スイッチ(event.getAction()){ ケースMotionEvent.ACTION_DOWN: { X = event.getX()。 } ブレーク; ケースMotionEvent.ACTION_MOVE: 破ります。 ケースMotionEvent.ACTION_UP: 破ります。 } trueを返します。 }
これらは一般的に、カスタムリライトすることにより、これらのメソッドを書き換え使用される方法は、我々は、カスタムコントロールの基本的な概要を達成することができます。ここでは、制御下にあるイベント傍受機構の原理を理解するために来ます。
イベント遮断機構解析
私たちは、のViewGroupのViewGroupまたはビューよりもがあるかもしれない、制御構造がツリー構造で、前にも言ってきた、そして、タッチイベントは、各ビューとのViewGroupそれに割り当てられているか正確です。私たちは、ViewGroupB内部の彼の巣に、ViewGroupAがあることを前提としますが、内部ViewGroupBにするだけでなく、ビューでネストされました。我々はViewGroupAクラスを書き換えるとき、私たちは、これらの3つの方法の内部を書き換える必要があります。
dispatchTouchEvent()
onInterceptTouchEvent()
onTouchEvent()
表示を書き換えるときに、我々は2つのメソッドをオーバーライドする必要があります:
dispatchTouchEvent()
onTouchEvent()
名前を見る以上でのViewGroup、見ることができるonInterceptTouchEvent()コアの方法、この方法がイベントをインターセプトすることです。それぞれの方法を見てログインし、[表示]をクリックして、彼らはメソッド呼び出しの順序を見つけます:
まず、呼び出しViewGroupAのクラスdispatchTouchEventを()と onInterceptTouchEvent() 。
そして、呼び出しViewGroupBのクラスdispatchTouchEvent()とonInterceptTouchEvent() 。
次に見るdispatchTouchEvent()メソッドを。
この順序は、イベント・デリバリーの呼び出しの順序で、一連のイベントが処理されます。
ビュー onTouchEventの()。
ViewGroupBのonTouchEvent()。
ViewGroupAのonTouchEvent()。
したがって、イベントの分布は、上のViewGroupで公開され、見ることができ、その後、発行層ごと。ハンドルのイベントは、それが層によって下にあるビュー、層によって処理して、アップロードされます。前にも言ってきた、onInterceptTouchEventは()イベントのコアは、その後、傍受限り、戻り値がtrueであるとして、それを設定し、それは、それはもはや発行され、イベントを傍受することはできませんが、することですonTouchEvent()がないイベントハンドラの後、falseを返します。アップロードの前に。分布と荒仕上げを説明するために、イベントの流れを遮断します。
最後に、このブログは私が「アンドロイドヒーローズ」を読んで、私は、カスタムビューの友人を学んでいる助けることを願っていことを確認して要約することで、一方、指摘を歓迎して、間違った場所を理解する必要があります。