package mobi.monaca.framework.nativeui.component; import static mobi.monaca.framework.nativeui.UIUtil.createBitmapWithColorFilter; import static mobi.monaca.framework.nativeui.UIUtil.updateJSONObject; import java.io.IOException; import mobi.monaca.framework.nativeui.ComponentEventer; import mobi.monaca.framework.nativeui.DefaultStyleJSON; import mobi.monaca.framework.nativeui.NonScaleBitmapDrawable; import mobi.monaca.framework.nativeui.UIContext; import mobi.monaca.framework.nativeui.UIUtil; import mobi.monaca.framework.nativeui.UIValidator; import mobi.monaca.framework.nativeui.component.view.MonacaButton; import mobi.monaca.framework.nativeui.exception.NativeUIException; import mobi.monaca.framework.nativeui.exception.NativeUIIOException; import org.json.JSONException; import org.json.JSONObject; import android.content.Context; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.StateListDrawable; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageButton; public class ButtonComponent extends ToolbarComponent { protected FrameLayout layout; protected MonacaButton button; protected MonacaImageButton imageButton; protected ComponentEventer eventer; protected static final String[] BUTTON_VALID_KEYS = { "component", "style", "iosStyle", "androidStyle", "id", "event" }; protected static final String[] STYLE_VALID_KEYS = { "visibility", "disable", "opacity", "backgroundColor", "activeTextColor", "textColor", "image", "innerImage", "text" }; public ButtonComponent(UIContext context, JSONObject buttonJSON) throws NativeUIException, JSONException { super(context, buttonJSON); UIValidator.validateKey(context, getComponentName() + " style", style, getStyleValidKeys()); buildEventer(); initView(); } // to be overriden by BackButton Component protected String[] getStyleValidKeys(){ return STYLE_VALID_KEYS; } private void buildEventer() throws NativeUIException, JSONException { this.eventer = new ComponentEventer(uiContext, getComponentJSON().optJSONObject("event")); } public ComponentEventer getUIEventer() { return eventer; } protected void initView() throws NativeUIException { layout = new FrameLayout(uiContext); layout.setClickable(true); button = new MonacaButton(uiContext); button.getButton().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { eventer.onTap(); } }); button.getInnerImageButton().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { eventer.onTap(); } }); imageButton = new MonacaImageButton(uiContext); imageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { eventer.onTap(); } }); layout.addView(button); layout.addView(imageButton); style(); } public View getView() { return layout; } @Override protected void finalize() throws Throwable { super.finalize(); imageButton.setBackgroundDrawable(null); } /** * visibility: true / false [bool] (default: true) disable: true / false * [bool] (default: false) opacity: 0.0~1.0 [float] (default: 1.0) * backgroundColor: #000000 [string] (default: #000000) activeColor: #000000 * [string] (default: #0000FF) textColor: #000000 [string] (default: * #FFFFFF) image: hoge.png (このファイルからみたときの相対パス) [string] text: テキスト [string] * @throws NativeUIException */ protected void style() throws NativeUIException { if (style.optString("image").length() > 0) { button.setVisibility(View.GONE); imageButton.setVisibility(View.VISIBLE); styleImageButton(); } else { button.setVisibility(View.VISIBLE); imageButton.setVisibility(View.GONE); styleButton(); } } protected void styleButton() throws NativeUIException { button.updateStyle(style); button.style(); Bitmap bitmap = readImage("innerImage"); if( bitmap != null ) { ImageButton imageButton = button.getInnerImageButton(); imageButton.setImageBitmap(bitmap); } } protected void styleImageButton() throws NativeUIIOException { imageButton.setVisibility(style.optBoolean("visibility", true) ? View.VISIBLE : View.GONE); imageButton.setBackgroundColor(0); imageButton.setEnabled(!style.optBoolean("disable", false)); Bitmap bitmap = readImage("image"); if(bitmap != null){ if (imageButton.getHeight() > 0) { int scaledHeight = imageButton.getHeight(); bitmap = UIUtil.resizeBitmap(bitmap, scaledHeight); } Drawable drawable = new ImageButtonDrawable(new NonScaleBitmapDrawable(bitmap)); imageButton.setBackgroundDrawable(drawable); imageButton.setPadding(0, 0, 0, 0); }else{ imageButton.setBackgroundDrawable(null); } } @Override public void updateStyle(JSONObject update) throws NativeUIException { updateJSONObject(style, update); style(); } public static class ButtonDrawable extends LayerDrawable { protected int backgroundColor, pressedBackgroundColor; private ButtonDrawable(Drawable drawable) { super(new Drawable[] { drawable }); } @Override protected boolean onStateChange(int[] states) { for (int state : states) { if (state == android.R.attr.state_pressed) { super.setColorFilter(0x66000000, Mode.MULTIPLY); } else { super.clearColorFilter(); } } return super.onStateChange(states); } @Override public boolean isStateful() { return true; } } public class ImageButtonDrawable extends StateListDrawable { protected int backgroundColor, pressedBackgroundColor; private ImageButtonDrawable(Drawable drawable) { super(); Drawable pressed = new BitmapDrawable(uiContext.getResources(), createBitmapWithColorFilter(drawable, new PorterDuffColorFilter(0x66000000, PorterDuff.Mode.MULTIPLY))); Drawable disabled = new BitmapDrawable(uiContext.getResources(), createBitmapWithColorFilter(drawable, new PorterDuffColorFilter(0x66000000, PorterDuff.Mode.MULTIPLY))); addState(new int[] { android.R.attr.state_pressed }, pressed); addState(new int[] { -android.R.attr.state_enabled }, disabled); addState(new int[0], drawable.mutate()); } } public class MonacaImageButton extends Button { public MonacaImageButton(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Bitmap bitmap; try { bitmap = readImage("image"); if (bitmap != null) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); int resolvedWidth = resolveSize(width, widthMeasureSpec); int resolvedHeight = resolveSize(height, heightMeasureSpec); setMeasuredDimension(resolvedWidth, resolvedHeight); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } catch (NativeUIIOException e) { e.printStackTrace(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { try { resizeImage(); } catch (NativeUIIOException e) { e.printStackTrace(); } super.onSizeChanged(w, h, oldw, oldh); } private void resizeImage() throws NativeUIIOException { Bitmap bitmap = readImage("image"); if (bitmap != null) { if (getMeasuredHeight() > 0) { int scaledHeight = getMeasuredHeight(); bitmap = UIUtil.resizeBitmap(bitmap, scaledHeight); } Drawable drawable = new ImageButtonDrawable(new NonScaleBitmapDrawable(bitmap)); imageButton.setBackgroundDrawable(drawable); imageButton.setPadding(0, 0, 0, 0); } else { imageButton.setBackgroundDrawable(null); } } } private Bitmap readImage(String imageKeyName) throws NativeUIIOException { String imagePath = style.optString(imageKeyName); if (!TextUtils.isEmpty(imagePath)) { try { Bitmap bitmap = uiContext.readScaledBitmap(imagePath); return bitmap; } catch (IOException e) { NativeUIIOException exception = new NativeUIIOException(getComponentName() + " style", imageKeyName, imagePath, e.getMessage()); throw exception; } } return null; } @Override public String[] getValidKeys() { return BUTTON_VALID_KEYS; } @Override public String getComponentName() { return "Button"; } @Override public JSONObject getDefaultStyle() { return DefaultStyleJSON.button(); } }