UI Android

/* 
 * Copyright (C) 2008 OpenIntents.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//package org.openintents.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
 * BrightnessSlider.
 * 
 * @author Peli, based on API demo code.
 * 
 */
public class ColorSlider extends View {
  /** Default widget width */
  public int defaultWidth;
  /** Default widget height */
  public int defaultHeight;
  
    private Paint mPaint;
    private int mColor1;
    private int mColor2;
    private OnColorChangedListener mListener;
  /**
   * Constructor. This version is only needed for instantiating the object
   * manually (not from a layout XML file).
   * 
   * @param context
   */
  public ColorSlider(Context context) {
    super(context);
    init();
  }
  /**
   * Construct object, initializing with any attributes we understand from a
   * layout file.
   * 
   * These attributes are defined in res/values/attrs.xml .
   * 
   * @see android.view.View#View(android.content.Context,
   *      android.util.AttributeSet, java.util.Map)
   */
  public ColorSlider(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO what happens with inflateParams
    init();
  }
  /**
   * Initializes variables.
   */
  void init() {
    
    mColor1 = 0xFFFFFFFF;
    mColor2 = 0xFF000000;
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);
  }
    @Override 
    protected void onDraw(Canvas canvas) {
    Shader s = new LinearGradient(0, 0, 0, getHeight(), mColor1, mColor2, Shader.TileMode.CLAMP);
        mPaint.setShader(s);
      
      canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
    }
    
  /**
   * @see android.view.View#measure(int, int)
   */
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(measureWidth(widthMeasureSpec),
        measureHeight(heightMeasureSpec));
  }
  /**
   * Determines the width of this view
   * 
   * @param measureSpec
   *            A measureSpec packed into an int
   * @return The width of the view, honoring constraints from measureSpec
   */
  private int measureWidth(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if (specMode == MeasureSpec.EXACTLY) {
      // We were told how big to be
      result = specSize;
    } else {
      // Default width:
      result = defaultWidth;
      if (specMode == MeasureSpec.AT_MOST) {
        // Respect AT_MOST value if that was what is called for by
        // measureSpec
        result = Math.min(result, specSize);
      }
    }
    return result;
  }
  /**
   * Determines the height of this view
   * 
   * @param measureSpec
   *            A measureSpec packed into an int
   * @return The height of the view, honoring constraints from measureSpec
   */
  private int measureHeight(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if (specMode == MeasureSpec.EXACTLY) {
      // We were told how big to be
      result = specSize;
    } else {
      // Default height
      result = defaultHeight;
      if (specMode == MeasureSpec.AT_MOST) {
        // Respect AT_MOST value if that was what is called for by
        // measureSpec
        result = Math.min(result, specSize);
      }
    }
    return result;
  }
    
  public void setColors(int color1, int color2) {
    mColor1 = color1;
    mColor2 = color2;
        
        invalidate();
  }
  public void setOnColorChangedListener(
      OnColorChangedListener colorListener) {
    mListener = colorListener;
  }
    
    private int ave(int s, int d, float p) {
        return s + java.lang.Math.round(p * (d - s));
    }
    private int interpColor(int color1, int color2, float unit) {
        if (unit <= 0) {
            return color1;
        }
        if (unit >= 1) {
            return color2;
        }
        
        float p = unit;
        // now p is just the fractional part [0...1) and i is the index
        int c0 = color1;
        int c1 = color2;
        int a = ave(Color.alpha(c0), Color.alpha(c1), p);
        int r = ave(Color.red(c0), Color.red(c1), p);
        int g = ave(Color.green(c0), Color.green(c1), p);
        int b = ave(Color.blue(c0), Color.blue(c1), p);
        
        return Color.argb(a, r, g, b);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
              
              float unit = (float) y / ((float) getHeight()); 
              
                int newcolor = interpColor(mColor1, mColor2, unit);
              if (mListener != null) {
                mListener.onColorChanged(this, newcolor);
              }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                
                break;
        }
        return true;
    }
}
/**
 * Interface for notifications of position change of slider.
 * 
 * @author Peli
 */
 interface OnColorChangedListener {
  /**
   * This method is called when the user changed the color.
   * 
   * This works in touch mode, by dragging the along the 
   * color circle with the finger.
   */
  void onColorChanged(View view, int newColor);
  
  /**
   * This method is called when the user clicks the center button.
   * 
   * @param colorcircle
   * @param newColor
   */
  void onColorPicked(View view, int newColor);
}