簡単なカスタムDialogFragment

26063 ワード

1、概要
DialogFragmentはandroid 3.0で導入された.Activityのコンテンツの上にモダリティを表示するための特別なFragmentです.一般的には、警告ボックス、入力ボックス、確認ボックスなどを表示します.DialogFragmentが生成される前に、ダイアログボックスを作成します.一般的にAlertDialogとDialogが使用されます.注意:Dialogを使用してダイアログを直接作成することは推奨されません.
2、メリットと使い方
DialogFragmentを使用してダイアログボックスを管理します.画面を回転したり、戻るキーを押したりすると、宣言サイクルをよりよく管理できます.これはFragmentとほぼ一致する宣言サイクルです.また、DialogFragmentでは、開発者がDialogを埋め込んだコンポーネントとして再利用することもできます.Fragmentのようなものです(大画面と小画面で異なる効果を表示できます).
以上の参照:http://blog.csdn.net/lmj623565791/article/details/37815413
そんなに辛抱強くない学生が直接逃げないように、余計なことは言わないで効果図を先に出してください.
非常に簡単な中間にアニメーションがあります.
カスタムloadingViewの効果は次のとおりです.
public class LoadingView extends View implements ValueAnimator.AnimatorUpdateListener {
    private Context context;
    private Paint paint;
    private PathMeasure pathMeasure;
    private Path showPath;
    private int mHeight;
    private int mWith;
    private ValueAnimator valueAnimator;
    private float dtPath;
    private float startPoint;
    private int radius = 80;

    public LoadingView(Context context) {
        super(context);
        init(context);
    }


    public LoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        this.context = context;
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(Displayutil.dip2px(getContext(), 3));
        paint.setStyle(Paint.Style.STROKE);
        Path path = new Path();
        path.addCircle(0, 0, radius, Path.Direction.CW);
        pathMeasure = new PathMeasure(path, false);
        valueAnimator = ValueAnimator.ofFloat(0, ((float) (2 * radius * Math.PI) / 4));
        valueAnimator.setDuration(2000).setRepeatCount(Animation.INFINITE);
        valueAnimator.addUpdateListener(this);
        valueAnimator.start();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        //  wrap_content         200dp
        int minSize = Displayutil.dip2px(context, radius);
        // wrap_content specMode AT_MOST  ,      /    specSize
        //         specSize   parentSize,             
        //  wrap_content          ,    martch_parent
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(minSize, minSize);
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(minSize, heightSpecSize);
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSpecSize, minSize);
        }


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mHeight = getMeasuredHeight();
        mWith = getMeasuredWidth();
        canvas.translate(mWith / 2, getHeight() / 2);
        Path path = new Path();
        pathMeasure.getSegment(startPoint, startPoint , path, true);
        if (startPoint + dtPath < 2 * radius * Math.PI) {
            pathMeasure.getSegment(startPoint, startPoint + dtPath, path, true);
        } else {
            pathMeasure.getSegment(startPoint, (float) (2 * radius * Math.PI), path, true);
        }

        canvas.drawPath(path, paint);
    }


    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        dtPath = (float) animation.getAnimatedValue();
        startPoint = dtPath * ((float) (2 * radius * Math.PI)) / ((float) (2 * radius * Math.PI) / 4);
        if(startPoint!=0){
            postInvalidateDelayed(300);

        }
    }


    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        valueAnimator.end();
    }
}

次は一歩ずつ
1 view処理onMeasureを継承し、
ここでは、warp_contentの書き方は固定して、注釈はとても詳しく書いて、理解しない提案、viewmeasureの過程のソースコードを見て、詳しく言わないで、もし必要ならば、後で私は1篇のブログを書いて続けます.
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        //  wrap_content         200dp
        int minSize = Displayutil.dip2px(context, radius);
        // wrap_content specMode AT_MOST  ,      /    specSize
        //         specSize   parentSize,             
        //  wrap_content          ,    martch_parent
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(minSize, minSize);
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(minSize, heightSpecSize);
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSpecSize, minSize);
        }

2 initメソッドを見る
private void init(Context context) {
    this.context = context;
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(Color.RED);
    paint.setStrokeWidth(Displayutil.dip2px(getContext(), 3));
    paint.setStyle(Paint.Style.STROKE);
    Path path = new Path();
    path.addCircle(0, 0, radius, Path.Direction.CW);
    pathMeasure = new PathMeasure(path, false);
    valueAnimator = ValueAnimator.ofFloat(0, ((float) (2 * radius * Math.PI) / 4));
    valueAnimator.setDuration(2000).setRepeatCount(Animation.INFINITE);
    valueAnimator.addUpdateListener(this);
    valueAnimator.start();
}

Initは3つのことをしました.
1ブラシを初期化
2計画ができました.私たちが取るpathパスは、リングであり、私たちの後ろに取るパスはこのリングから取ったものです.
    Path path = new Path();
    path.addCircle(0, 0, radius, Path.Direction.CW);

3初期話はプロパティアニメーションで、リスニングが設定されています.
リスニング内のメソッド.
@Override
public void onAnimationUpdate(ValueAnimator animation) {
    dtPath = (float) animation.getAnimatedValue();
    startPoint = dtPath * ((float) (2 * radius * Math.PI)) / ((float) (2 * radius * Math.PI) / 4);
    if(startPoint!=0){
        postInvalidateDelayed(300);

    }
}

dapathは円弧の長さを描く必要があります.valueanimatiorを見ると、最小は0で、最大は円の周長の1/4であることがわかります.
startPoint円弧の描画を開始する位置は、原理が簡単で、dapthの実際の値の最大値に対する割合に基づいて、描画を開始する位置を決定し、dapthの長さが1周期変化することを保証し、描画を開始する位置が円周に沿って1周移動します.
その後invalidateDekayedはviewを新しい描画から引き起こし、
処理ondraw()
ここがアニメーションのポイントです.ここではvalueAnimatorを実装します.補間ルート推定器をカスタマイズして実装することもできます.それは少し複雑です.ここでは直接アニメーションを使用していますが、コントロールをカスタマイズするときは、アニメーションを使用して、メモリの漏洩に注意してください.後で話します.次の行は行ごとに言います.
mHeight = getMeasuredHeight();         mWith = getMeasuredWidth(); スペースの幅を取得し、getheight()getWidth()を直接使用しないように注意すると、幅が得られない可能性があります.これもviewテストの基礎です.多くは言いません.        canvas.translate(mWith/2, getHeight()/2);         Path path = new Path();      
    pathMeasure.getSegment(startPoint, startPoint + dtPath, path, true);

これは最も重要な方法で、4つのパラメータはそれぞれ代表して、pathの起点を切り取り始めて、pathは終点を切り取って、pathは私たちが切り取る対象を保存するために使用して、最後のパラメータは切り取る経路が犬が最初に接続する必要があることを示しています.        if (startPoint + dtPath < 2 * radius * Math.PI) {             pathMeasure.getSegment(startPoint, startPoint + dtPath, path, true);         } else {             pathMeasure.getSegment(startPoint, (float) (2 * radius * Math.PI), path, true);         }
描画canvas.drawPath(path, paint);
@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    valueAnimator.end();
}

アニメーションの使用によるメモリ漏洩の問題を解決します.viewがwindowを離れるとアニメーションが閉じます.
dialogFragmentは簡単だ
public class LoadingDialog extends DialogFragment{

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
        getDialog().setCanceledOnTouchOutside(false);
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        return inflater.inflate(R.layout.loding_dialog,null);
    }
}

タイトルを外し、styleで背景を透明にしてdialogのレイアウトを設定し、
注意dailogfragmentを使用する場合oncreateviewとonCreateDIalogの方法は1つしか実現できません.そうしないと、間違いを報告します.
これで簡単なdialogfragmentが完成しました.