package libs.mjn.prettydialog; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.Shader; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.support.v7.app.AppCompatDialog; import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.RotateAnimation; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import static android.widget.ImageView.ScaleType.CENTER_CROP; import static android.widget.ImageView.ScaleType.CENTER_INSIDE; /** * Created by mJafarinejad on 8/15/2017. */ public class PrettyDialog extends AppCompatDialog { Resources resources; LinearLayout ll_content, ll_buttons; PrettyDialogCircularImageView iv_icon; RotateAnimation close_rotation_animation; boolean icon_animation = true; TextView tv_title, tv_message; Typeface typeface; PrettyDialog thisDialog; Context context; public PrettyDialog(Context context) { super(context); this.context = context; getWindow().requestFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.pdlg_layout); setCancelable(true); resources = context.getResources(); getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); DisplayMetrics displayMetrics = resources.getDisplayMetrics(); float pxWidth = displayMetrics.widthPixels; getWindow().setLayout((int)(pxWidth*0.75),ViewGroup.LayoutParams.WRAP_CONTENT); getWindow().getAttributes().windowAnimations = R.style.pdlg_default_animation; thisDialog = this; setupViews_Base(); } private void setupViews_Base(){ ll_content = (LinearLayout) findViewById(R.id.ll_content); ll_buttons = (LinearLayout) findViewById(R.id.ll_buttons); iv_icon = (PrettyDialogCircularImageView) findViewById(R.id.iv_icon); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.setMargins(0, resources.getDimensionPixelSize(R.dimen.pdlg_icon_size)/2, 0, 0); ll_content.setLayoutParams(lp); ll_content.setPadding(0,(int)(1.25*resources.getDimensionPixelSize(R.dimen.pdlg_icon_size)/2),0,resources.getDimensionPixelSize(R.dimen.pdlg_space_1_0x)); close_rotation_animation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); close_rotation_animation.setDuration(300); close_rotation_animation.setRepeatCount(Animation.ABSOLUTE); close_rotation_animation.setInterpolator(new DecelerateInterpolator()); close_rotation_animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { thisDialog.dismiss(); } @Override public void onAnimationRepeat(Animation animation) { } }); iv_icon.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: v.setAlpha(0.7f); return true; case MotionEvent.ACTION_UP: v.setAlpha(1.0f); if(icon_animation) { v.startAnimation(close_rotation_animation); } return true; default: return false; } } }); tv_title = (TextView) findViewById(R.id.tv_title); tv_title.setVisibility(View.GONE); tv_message = (TextView) findViewById(R.id.tv_message); tv_message.setVisibility(View.GONE); } public PrettyDialog setGravity(int gravity){ getWindow().setGravity(gravity); return this; } public PrettyDialog addButton(String text, Integer textColor, Integer backgroundColor, /*BUTTON_TYPE type,*/ PrettyDialogCallback callback){ PrettyDialogButton button = new PrettyDialogButton(context,text, textColor, backgroundColor, typeface, /*type,*/ callback); int margin = resources.getDimensionPixelSize(R.dimen.pdlg_space_1_0x); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.setMargins(margin, margin, margin, 0); button.setLayoutParams(lp); ll_buttons.addView(button); return this; } public PrettyDialog setTitle(String text){ if(text.trim().length()>0) { tv_title.setVisibility(View.VISIBLE); tv_title.setText(text); } else { tv_title.setVisibility(View.GONE); } return this; } public PrettyDialog setTitleColor(Integer color){ //tv_title.setTextColor(ContextCompat.getColor(context,color==null?R.color.pdlg_color_black : color)); tv_title.setTextColor(context.getResources().getColor(color==null?R.color.pdlg_color_black : color)); return this; } public PrettyDialog setMessage(String text){ if(text.trim().length()>0) { tv_message.setVisibility(View.VISIBLE); tv_message.setText(text); } else { tv_message.setVisibility(View.GONE); } return this; } public PrettyDialog setMessageColor(Integer color){ //tv_message.setTextColor(ContextCompat.getColor(context,color==null?R.color.pdlg_color_black :color)); tv_message.setTextColor(context.getResources().getColor(color==null?R.color.pdlg_color_black :color)); return this; } public PrettyDialog setIcon(Integer icon){ iv_icon.setImageResource(icon==null?R.drawable.pdlg_icon_close :icon); icon_animation = false; iv_icon.setOnTouchListener(null); return this; } public PrettyDialog setIconTint(Integer color){ //iv_icon.setColorFilter(ContextCompat.getColor(context,color==null?default_icon_tint:color), PorterDuff.Mode.MULTIPLY); if(color==null){ iv_icon.setColorFilter(null); } else iv_icon.setColorFilter(context.getResources().getColor(color), PorterDuff.Mode.MULTIPLY); return this; } public PrettyDialog setIconCallback(final PrettyDialogCallback callback){ iv_icon.setOnTouchListener(null); if (callback != null) { iv_icon.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: v.setAlpha(0.7f); return true; case MotionEvent.ACTION_UP: v.setAlpha(1.0f); callback.onClick(); return true; default: return false; } } }); } return this; } public PrettyDialog setIcon(Integer icon, Integer iconTint, final PrettyDialogCallback callback){ icon_animation = false; iv_icon.setImageResource(icon==null?R.drawable.pdlg_icon_close :icon); //iv_icon.setColorFilter(ContextCompat.getColor(context,iconTint==null?default_icon_tint:iconTint), PorterDuff.Mode.MULTIPLY); if(iconTint==null) { iv_icon.setColorFilter(null); } else iv_icon.setColorFilter(context.getResources().getColor(iconTint), PorterDuff.Mode.MULTIPLY); iv_icon.setOnTouchListener(null); if (callback != null) { iv_icon.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: v.setAlpha(0.7f); return true; case MotionEvent.ACTION_UP: v.setAlpha(1.0f); callback.onClick(); return true; default: return false; } } }); } return this; } public PrettyDialog setTypeface(Typeface tf){ typeface = tf; tv_title.setTypeface(tf); tv_message.setTypeface(tf); for (int i=0;i<ll_buttons.getChildCount();i++){ PrettyDialogButton button = (PrettyDialogButton) ll_buttons.getChildAt(i); button.setTypeface(tf); button.requestLayout(); } return this; } public PrettyDialog setAnimationEnabled(boolean enabled){ if (enabled){ getWindow().getAttributes().windowAnimations = R.style.pdlg_default_animation; } else { getWindow().getAttributes().windowAnimations = R.style.pdlg_no_animation; } return this; } protected static class PrettyDialogCircularImageView extends AppCompatImageView { // Properties private float borderWidth; private int canvasSize; private ColorFilter colorFilter; // Object used to draw private Bitmap image; private Drawable drawable; private Paint paint; private Paint paintBorder; private Paint paintBackground; //region Constructor & Init Method public PrettyDialogCircularImageView(final Context context) { this(context, null); } public PrettyDialogCircularImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public PrettyDialogCircularImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); } private void init(Context context, AttributeSet attrs, int defStyleAttr) { // Init paint paint = new Paint(); paint.setAntiAlias(true); paintBorder = new Paint(); paintBorder.setAntiAlias(true); paintBackground = new Paint(); paintBackground.setAntiAlias(true); setBorderWidth(0); setBorderColor(Color.WHITE); setBackgroundColor(Color.WHITE); } //endregion //region Set Attr Method public void setBorderWidth(float borderWidth) { this.borderWidth = borderWidth; requestLayout(); invalidate(); } public void setBorderColor(int borderColor) { if (paintBorder != null) paintBorder.setColor(borderColor); invalidate(); } public void setBackgroundColor(int backgroundColor) { if (paintBackground != null) paintBackground.setColor(backgroundColor); invalidate(); } @Override public void setColorFilter(ColorFilter colorFilter) { if (this.colorFilter == colorFilter) return; this.colorFilter = colorFilter; drawable = null; // To force re-update shader invalidate(); } @Override public ScaleType getScaleType() { ScaleType currentScaleType = super.getScaleType(); return currentScaleType == null || currentScaleType != CENTER_INSIDE ? CENTER_CROP : currentScaleType; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != CENTER_CROP && scaleType != CENTER_INSIDE) { throw new IllegalArgumentException(String.format("ScaleType %s not supported. " + "Just ScaleType.CENTER_CROP & ScaleType.CENTER_INSIDE are available for this library.", scaleType)); } else { super.setScaleType(scaleType); } } //endregion //region Draw Method @Override public void onDraw(Canvas canvas) { // Load the bitmap loadBitmap(); // Check if image isn't null if (image == null) return; if (!isInEditMode()) { canvasSize = Math.min(canvas.getWidth(), canvas.getHeight()); } // circleCenter is the x or y of the view's center // radius is the radius in pixels of the cirle to be drawn // paint contains the shader that will texture the shape int circleCenter = (int) (canvasSize - (borderWidth * 2)) / 2; float margeWithShadowRadius = 0; // Draw Border canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - margeWithShadowRadius, paintBorder); // Draw Circle background canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - margeWithShadowRadius, paintBackground); // Draw CircularImageView canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - margeWithShadowRadius, paint); } private void loadBitmap() { if (drawable == getDrawable()) return; drawable = getDrawable(); image = drawableToBitmap(drawable); updateShader(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); canvasSize = Math.min(w, h); if (image != null) updateShader(); } private void updateShader() { if (image == null) return; // Create Shader BitmapShader shader = new BitmapShader(image, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // Center Image in Shader float scale = 0; float dx = 0; float dy = 0; switch (getScaleType()) { case CENTER_CROP: if (image.getWidth() * getHeight() > getWidth() * image.getHeight()) { scale = getHeight() / (float) image.getHeight(); dx = (getWidth() - image.getWidth() * scale) * 0.5f; } else { scale = getWidth() / (float) image.getWidth(); dy = (getHeight() - image.getHeight() * scale) * 0.5f; } break; case CENTER_INSIDE: if (image.getWidth() * getHeight() < getWidth() * image.getHeight()) { scale = getHeight() / (float) image.getHeight(); dx = (getWidth() - image.getWidth() * scale) * 0.5f; } else { scale = getWidth() / (float) image.getWidth(); dy = (getHeight() - image.getHeight() * scale) * 0.5f; } break; } Matrix matrix = new Matrix(); matrix.setScale(scale, scale); matrix.postTranslate(dx, dy); shader.setLocalMatrix(matrix); // Set Shader in Paint paint.setShader(shader); // Apply colorFilter paint.setColorFilter(colorFilter); } private Bitmap drawableToBitmap(Drawable drawable) { if (drawable == null) { return null; } else if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { // Create Bitmap object out of the drawable Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } //endregion //region Measure Method @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); setMeasuredDimension(width, height); } private int measureWidth(int measureSpec) { int result; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { // The parent has determined an exact size for the child. result = specSize; } else if (specMode == MeasureSpec.AT_MOST) { // The child can be as large as it wants up to the specified size. result = specSize; } else { // The parent has not imposed any constraint on the child. result = canvasSize; } return result; } private int measureHeight(int measureSpecHeight) { int result; int specMode = MeasureSpec.getMode(measureSpecHeight); int specSize = MeasureSpec.getSize(measureSpecHeight); if (specMode == MeasureSpec.EXACTLY) { // We were told how big to be result = specSize; } else if (specMode == MeasureSpec.AT_MOST) { // The child can be as large as it wants up to the specified size. result = specSize; } else { // Measure the text (beware: ascent is a negative number) result = canvasSize; } return result + 2; } //endregion } }