AndroidオープンソースフレームワークPowerfulViewLibrary-PowerfulEditTextの紹介とソースコード解析


この記事では、WeChatの公式アカウントguolinを許可しました.blog(郭霖)独占発表
転載は出典を明記してください.http://blog.csdn.net/chay_chan/article/details/63685905
AndroidオープンソースフレームワークPowerfulViewLibrary-PowerfulEditTextの紹介
自分が書いた前の2つのブログが郭霖(郭神と呼ばれる)に認められたことを喜んで、彼の微信の公衆番号に発表してくれると約束して、ブログを書く決心をさせました.私は一ヶ月一日もっとしたほうがましで、むやみに数えたくない.ブログを書くのは自分の技術と経験を分かち合うためである一方で、お互いに勉強したり、交流したり、進歩したりするためです.最近、PowerfulViewLibraryというオープンソースフレームワークの開発が決定しました.つまり、強力なViewライブラリです.主に開発を容易にするために、よく使われるコントロールをパッケージ化しています.以下は、関連する紹介と使用です.
PowerfulEditTextの機能
1.テキスト消去機能付き
 PowerfulEditTextには、レイアウトファイルのViewプロパティにfuncTypeを追加してcanClearと指定するだけで、次のようにテキストを消去する機能があります.



    



実行後の効果は次のとおりです.
  上図に示す削除アイコンはデフォルトですが、もちろん右側の削除ボタンのアイコンを指定することもできます.多drawableRight属性を追加するだけです.ここでは、通常の状態と押した状態のそれぞれに画像を設定するselectorを使用することをお勧めします.このように、アイコンを押すと、押した状態になります.selectorの作成は以下のようになります.


    
    


ソース分析:
public class PowerfulEditText extends EditText {

	/**    */
    private static final int TYPE_NORMAL = -1;
    /**         */
    private static final int TYPE_CAN_CLEAR = 0;
    /**           */
    private static final int TYPE_CAN_WATCH_PWD = 1;

     public PowerfulEditText(Context context) {
        this(context, null);
     }

     public PowerfulEditText(Context context, AttributeSet attrs) {
        //          ,           XML      
        this(context, attrs, android.R.attr.editTextStyle);
     }

     public PowerfulEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        ta = context.obtainStyledAttributes(attrs, R.styleable.PowerfulEditText);

        funcType = ta.getInt(R.styleable.PowerfulEditText_funcType, TYPE_NORMAL);

        ...

        init();
     }

}

  PowerfulEditTextはEditTextに継承されています.ここでは、通常タイプ、消去機能タイプ、パスワード表示機能の3つのタイプが定義されています.そのうち、2つ目の構造方法、つまり2つのパラメータのみの構造方法で、このクラスの3つ目の構造方法(3つのパラメータ付きの構造方法)を呼び出し、intタイプのパラメータを1つ多く伝える必要があります.ここでは以前他のViewを定義したときのように直接0を渡すのではなくandroidを伝える.R.attr.editTextStyle、そうでなければ多くの属性はXMLで定義できません.独自の論理操作init()メソッドは,3番目の構築メソッドで呼び出せばよい.
private void init() {
		//  EditText DrawableRight,                ,    
        mRightDrawable = getCompoundDrawables()[2];
		
		if (mRightDrawable == null) {
            //        
            if (funcType == TYPE_CAN_CLEAR) {
                //     ,         
                mRightDrawable = getResources().getDrawable(R.drawable.delete_selector);
            } 
        }

		//       ,            ,           
        setRightIconVisible(funcType == 0 ? false : true);
         //                
        addTextChangedListener(new TextWatcher() {
            /**
             *                     
             */
            @Override
            public void onTextChanged(CharSequence s, int start, int count,
                                      int after) {
		//            ,            ,          0       
                if (funcType == 0) {
                    setRightIconVisible(s.length() > 0);
                }

                if (textListener != null) {
                    textListener.onTextChanged(s, start, count, after);
                }
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                                          int after) {
                if (textListener != null) {
                    textListener.beforeTextChanged(s, start, count, after);
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (textListener != null) {
                    textListener.afterTextChanged(s);
                }
            }

    	});
    }


	/**
     *             ,  setCompoundDrawables EditText    
     *
     * @param visible
     */
    protected void setRightIconVisible(boolean visible) {
        Drawable right = visible ? mRightDrawable : null;
        setCompoundDrawables(getCompoundDrawables()[0],
                getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
    }

 
   /**
	 *           ,             ,    listen  *TextWatcher
	 */
    public interface TextListener {

        void onTextChanged(CharSequence s, int start, int count, int after);

        void beforeTextChanged(CharSequence s, int start, int count, int after);

        void afterTextChanged(Editable s);
    }

  init()メソッドでは、まず入力ボックス右側のDrawableオブジェクトを取得し、getCompoundDrawables()[2]で取得し、getCompoundDrawables()メソッドは入力ボックスの4つの方向アイコンを取得するためのメソッドであり、返されるタイプはDrawable配列であり、配列の要素ソートはそれぞれ左(0)上(1)右(2)下(3)下(3)の4つのDrawableであり、ここでは右側のアイコンオブジェクトを取得する必要があります.対応する下付きは2です.右側のアイコンmRightDrawableが空かどうかを判断する、空で現在の機能タイプがセルフクリア機能である場合、デフォルトのクリアアイコンを使用してgetResources()を呼び出す.getDrawable()は、対応するselectorをロードします.
  機能タイプがクリア機能付きタイプであるか否かを判断し、右側アイコンを初期化したときに表示するか否かを判断し、次にテキスト内容変化の傍受を設定し、テキスト内容の変化を傍受することにより、右側アイコンを表示するか否かを判断する.ここではTextWatcherがテキストの傍受を行うように設定されており、onTextChanged()メソッドで操作されているため、PowfulEditTextを使用する場合、テキストコンテンツの傍受で対応する操作を行う必要がある場合は、TextWatcherではなく、自分で定義したTextListenerを使用してコールバックを行う必要がある.
  入力ボックス右側アイコンクリックイベントの処理については、onTouchEvent()メソッドを書き換え、タッチ応答を処理して、タッチの位置が右側アイコンの範囲内にあるか否かを判断し、もしそうであれば、そのアイコンをクリックしたものとみなす.
    /**
     *          EditText      ,                     
     *             EditText    -            -         
     * EditText    -                      ,         
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getCompoundDrawables()[2] != null) {

                boolean isTouched = event.getX() > (getWidth() - getTotalPaddingRight())
                        && (event.getX() < ((getWidth() - getPaddingRight())));

                if (isTouched) {

                    if (onRightClickListener == null) {
                        if (funcType == TYPE_CAN_CLEAR) {
                            //               ,        ,      
                            this.setText("");
                        } else if (funcType == TYPE_CAN_WATCH_PWD) {
                            //               ,          ,          
                            ...
                        }
                    } else {
                        //      
                        ...
                    }
                }
            }
        }

        return super.onTouchEvent(event);
    }

 押下されたx値がEditTextの幅-(アイコンからコントロールの右側のピッチ+アイコンの幅)(getTotalPaddingRight()とEditTextの幅-アイコンからコントロールの右側のピッチの間にある場合は、アイコン(正確な計算のためにy値方向の判断が考えられる)をクリックして対応する操作を行い、右側アイコンのクリックイベントが設定されていなければ、現在、パージ機能付きタイプに属している場合は、デフォルトでテキストがパージされます.
2.暗証番号入力ボックスを持参して明文暗号文フォーマットを切り替える機能
 PowerfulEditTextには、パスワード入力ボックスで明文の暗号文フォーマットを切り替える機能があります.現在、多くのAppパスワード入力欄では、パスワードの明文、暗号文の表示が一般的にサポートされています.この機能を使用する必要がある場合は、funcTypeでcanWatchPwdと指定すれば、この機能を簡単に使用できます.


実行後の効果は次のとおりです.
ソース解析:
  も同様にonTouchEvent()メソッドで処理され、現在の機能タイプがパスワード表示機能タイプに属している場合はeyeOpenという標識に基づいて現在が明文であるか否かを判断し、もしそうであればクリックすると密文となり、そうでなければ明文となる.
 /**
     *          EditText      ,                     
     *             EditText    -            -         
     * EditText    -                      ,         
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (getCompoundDrawables()[2] != null) {

                boolean isTouched = event.getX() > (getWidth() - getTotalPaddingRight())
                        && (event.getX() < ((getWidth() - getPaddingRight())));

                if (isTouched) {

                    if (onRightClickListener == null) {
                        if (funcType == TYPE_CAN_CLEAR) {
                            //               ,        ,      
                            ...
                        } else if (funcType == TYPE_CAN_WATCH_PWD) {
                            //               ,          ,          
                            if (eyeOpen) {
                                //     
                                this.setTransformationMethod(PasswordTransformationMethod.getInstance());
                                eyeOpen = false;
                            } else {
                                //    
                                this.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
                                eyeOpen = true;
                            }
                            switchWatchPwdIcon();//    
                        }
                    } else {
                        //      
                        ...
                    }
                }
            }
        }

        return super.onTouchEvent(event);
    }


	/**
     *          
     */
    private void switchWatchPwdIcon() {
        if (eyeOpen) {
            //    
            setCompoundDrawables(getCompoundDrawables()[0],
                    getCompoundDrawables()[1], mEyeOpenDrawable, getCompoundDrawables()[3]);
        } else {
            //    
            setCompoundDrawables(getCompoundDrawables()[0],
                    getCompoundDrawables()[1], mRightDrawable, getCompoundDrawables()[3]);
        }
    }

入力ボックス明文と密文切り替えの設定には2つの方法があります.
方法1:
setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);//    
setInputType(EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); //    

方法2:
setTransformationMethod(PasswordTransformationMethod.getInstance());//    
setTransformationMethod(HideReturnsTransformationMethod.getInstance());//    

  上記の2つの方法はいずれも明文密文の切り替えが可能であるが,方法を切り替えるとEditTextのカーソルが一番左側に戻るので,ここでは使い方2を選び,個人的には体験したほうがよいと考える.
  上図に示す右側のアイコンはデフォルトであり、同じくパスワード表示をオンにするアイコンとパスワード表示をオフにするアイコンを指定することもでき、属性eyeOpenでパスワード参照をオンにするピクチャを指定し、eyeClosedでパスワード参照をオフにするピクチャを指定すればよい.以下のように、パスワード表示をオンにするアイコンを交換し、プロジェクトのデフォルトのアイコンic_launcher


実行後の効果は次のとおりです.
これでパスワード表示をオンにするアイコンが変更され、パスワード表示をオフにするアイコンも変更する必要がある場合はeyeCloseを指定し、対応するアイコンを参照できます.
3.drawableLeftとdrawableRightの画像サイズを設定する機能
  原生のEditTextは属性にdrawableLeftやdrawableRightピクチャの大きさを指定することはできないので、一般的に開発する過程で、一部のプログラマーは簡単で乱暴な方法で、幅が広くても小さいピクチャを直接引用します.しかし、異なる画面解像度では、互換性があまりよくありません.例えば、画面解像度の高い携帯電話で実行すると、アイコンがぼやけてしまいます.PowerfulEditTextではdrawableLeftとdrawableRightピクチャのアスペクトサイズを指定し、どのくらいのdpに指定できるかを指定できます.これにより、開発時に各解像度ピクチャフォルダに異なるサイズのアイコンを入れ、ピクチャのアスペクトプロパティを設定することで表示のサイズを制限することができます.以下に説明します.


Android开源框架PowerfulViewLibrary——PowerfulEditText的介绍和源码解析_第1张图片
図のようにdrawableLeftを指定した画像はic_Laucherは、画像が大きく見えますが、小さくしたい場合は、leftDrawableWidth、leftDrawableHeightを追加して左側の画像の幅を指定できます.


上記のコードでは、leftDrawableWidthとleftDrawableHeightのサイズを30 dpと指定しています.実行の効果は次のとおりです.
Android开源框架PowerfulViewLibrary——PowerfulEditText的介绍和源码解析_第2张图片
左側のアイコンが小さくなり、右側の画像の幅を設定することもできます.対応する属性はrightDrawableWidth、rightDrawableHeightです.
ソースコードの解析:
 public PowerfulEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    ta = context.obtainStyledAttributes(attrs, R.styleable.PowerfulEditText);
   
    ...

    init();
}

 if (leftDrawable != null) {
        leftWidth = ta.getDimensionPixelOffset(R.styleable.PowerfulEditText_leftDrawableWidth,leftDrawable.getIntrinsicWidth());
        leftHeight = ta.getDimensionPixelOffset(R.styleable.PowerfulEditText_leftDrawableHeight,leftDrawable.getIntrinsicHeight());
        leftDrawable.setBounds(0, 0, leftWidth, leftHeight);
    }

    if (mRightDrawable != null) {
        rightWidth = ta.getDimensionPixelOffset(R.styleable.PowerfulEditText_rightDrawableWidth,mRightDrawable.getIntrinsicWidth());
        rightHeight = ta.getDimensionPixelOffset(R.styleable.PowerfulEditText_rightDrawableWidth,mRightDrawable.getIntrinsicHeight());
        mRightDrawable.setBounds(0, 0, rightWidth, rightHeight);
        if (mEyeOpenDrawable != null) {
            mEyeOpenDrawable.setBounds(0, 0, rightWidth, rightHeight);
        }
       ...
    }

  ここではTypedArrayによりXMLで構成する対応するleftDrawableWidth、leftDrawableHeight、rightDrawableWidth、rightDrawableHeightのサイズを取得し、これらの属性が設定されていない場合はデフォルトでアイコンの幅と高さを使用し、その後Drawableを通過する.setBounds()メソッドでは、右側のアイコンの幅を設定し、両側のアイコンのサイズを変更します.
####右アイコンクリックイベントを設定####PowerfulEditTextも右画像のクリックイベントをサポートし、funcTypeがcanClearと指定されている場合は、デフォルトのクリックはテキストをクリアします.追加の操作が必要な場合は、検索入力ボックスなどのコールバックを設定できます.右側には検索ボタンがあり、クリックイベントのコールバックを設定する必要があります.
レイアウトファイル:
 

Activity
  PowerfulEditText petUsername = (PowerfulEditText) findViewById(R.id.pet);
    petUsername.setOnRightClickListener(new PowerfulEditText.OnRightClickListener() {
        @Override
        public void onClick(EditText editText) {
            String content = editText.getText().toString().trim();
            if (!TextUtils.isEmpty(content)){
                Toast.makeText(MainActivity.this, "      ", Toast.LENGTH_SHORT).show();
            }
        }
    });

実行効果は次のとおりです.
上のレイアウトファイルでは、通常のEditTextプロパティと同様にfuncTypeにはnormal(デフォルト)、canClear(消去機能付き)、canWatchPwd(パスワード表示機能付き)の3つのプロパティがあります.funcTypeを指定しない場合、デフォルトはnormal、一般的な方法です.
  Activityでは、PowerfulEditTextに右画像のクリックイベントを設定し、setOnRightClickListenerを呼び出してクリック後のコールバックを設定し、ここでクリックした後にテキスト内容があれば検索ロジックを実行します.
  ここではEditTextのいくつかの機能のみをカプセル化し、スタイルの変更については、開発者が自分のニーズに合わせて修正しなければならない.修正の仕方も難しくない.backgroundを自分で作成したxmlに指定すればよい.
  右アイコンクリックイベントについてのコールバックは、上記と一致しており、onTouchEvent()メソッドでは、タッチ範囲が右アイコン上に落ちているか否かを判断し、OnRightClickListenerがnullであるか否かを判断し、nullでなければコールバックを行う.OnRightClickListenerインタフェースは簡単で、コールバック時に現在のEditTextオブジェクトを渡し、右側のアイコンクリックイベントに対して独自の論理処理を行う必要がある場合はsetOnRightClickListener()を呼び出してコールバックを行う.
    /**
     *          
     */
    public interface OnRightClickListener {
        void onClick(EditText editText);
    }

PowerfulEditTextに関する属性はattrを表示することができる.xmlは一目瞭然で、以下の通りです.
 
    
    
        
        
        
    
    
    
    
    
    
    
    
    
    
    
    
    


####導入方式###プロジェクトルートディレクトリの下にあるbuild.gradleのallprojects{}にjitpackウェアハウスアドレスを追加します.次のようにします.
allprojects {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }//  jitpack    
    }
}

appのmoduleのbuildを開きます.gradle、dependencies{}に依存を追加します.次のようにします.
dependencies {
		......
        compile 'com.github.chaychan:PowerfulViewLibrary:1.0'
}

  このようにPowerfulViewLibraryの下のコントロールを使うことができて、現在EditTextのいくつかの機能だけをカプセル化して、後でいくつかのよく使うViewをカプセル化して、プロジェクトの開発を便利にして、私はPowerfulViewLibraryの更新とメンテナンスを維持することができて、みんなが私にいくつか提案することができることを望みます.
ソースgithubアドレス:https://github.com/chaychan/PowerfulViewLibrary.git