Android 仿PhotoShop调色板应用(四) 不同区域颜色选择的颜色生成响应

 Android 仿PhotoShop调色板应用(四) 不同区域颜色选择的颜色生成响应

 上一篇讲过了主体界面的绘制,这里讲解调色板应用中的另外一个核心: 颜色选择及生成.

ColorPcikerView中不同部分的选择和ColorPickerPanelView中颜色显示是怎样响应的呢?这里当然少不了回调函数:

ColorPickerView:

  1. public interface OnColorChangedListener {  
  2.     public void onColorChanged(int color);  
  3. }  


然后看一下轨迹球的事件处理:

  1. @Override  
  2. public boolean onTrackballEvent(MotionEvent event) {  
  3.   
  4.     float x = event.getX();  
  5.     float y = event.getY();  
  6.   
  7.     boolean update = false;//是否需要更新颜色  
  8.   
  9.   
  10.     if(event.getAction() == MotionEvent.ACTION_MOVE){  
  11.   
  12.         switch(mLastTouchedPanel){  
  13.   
  14.         case PANEL_SAT_VAL://饱和度&亮度选择区域  
  15.   
  16.             float sat, val;  
  17.   
  18.             sat = mSat + x/50f;  
  19.             val = mVal - y/50f;  
  20.   
  21.             if(sat < 0f){  
  22.                 sat = 0f;  
  23.             }  
  24.             else if(sat > 1f){  
  25.                 sat = 1f;  
  26.             }  
  27.   
  28.             if(val < 0f){  
  29.                 val = 0f;  
  30.             }  
  31.             else if(val > 1f){  
  32.                 val = 1f;  
  33.             }  
  34.   
  35.             mSat = sat;  
  36.             mVal = val;  
  37.   
  38.             update = true;  
  39.   
  40.             break;  
  41.   
  42.         case PANEL_HUE://色相选择区域  
  43.   
  44.             float hue = mHue - y * 10f;  
  45.   
  46.             if(hue < 0f){  
  47.                 hue = 0f;  
  48.             }  
  49.             else if(hue > 360f){  
  50.                 hue = 360f;  
  51.             }  
  52.   
  53.             mHue = hue;  
  54.   
  55.             update = true;  
  56.   
  57.             break;  
  58.   
  59.         case PANEL_ALPHA://透明度选择区域  
  60.   
  61.             if(!mShowAlphaPanel || mAlphaRect == null){  
  62.                 update = false;  
  63.             }  
  64.             else{  
  65.   
  66.                 int alpha = (int) (mAlpha - x*10);  
  67.   
  68.                 if(alpha < 0){  
  69.                     alpha = 0;  
  70.                 }  
  71.                 else if(alpha > 0xff){  
  72.                     alpha = 0xff;  
  73.                 }  
  74.   
  75.                 mAlpha = alpha;  
  76.   
  77.   
  78.                 update = true;  
  79.             }  
  80.   
  81.             break;  
  82.         }  
  83.   
  84.   
  85.     }  
  86.   
  87.   
  88.     if(update){//如果需要更新,调用对用的回调函数并重新绘制  
  89.   
  90.         if(mListener != null){//参数需要由HSV格式的float数组转换为ARGB格式的 int 参数  
  91.             mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));  
  92.         }  
  93.   
  94.          invalidate();  
  95.          return true;  
  96.     }  
  97.   
  98.   
  99.     return super.onTrackballEvent(event);  
  100. }  


ColorPickerView中关于触摸事件的处理:

  1. @Override  
  2.     public boolean onTouchEvent(MotionEvent event) {  
  3.   
  4.         boolean update = false;  
  5.   
  6.         switch(event.getAction()){  
  7.   
  8.         case MotionEvent.ACTION_DOWN:  
  9.   
  10.             mStartTouchPoint = new Point((int)event.getX(), (int)event.getY());  
  11.   
  12.             update = moveTrackersIfNeeded(event);  
  13.   
  14.             break;  
  15.   
  16.         case MotionEvent.ACTION_MOVE:  
  17.   
  18.             update = moveTrackersIfNeeded(event);  
  19.   
  20.             break;  
  21.   
  22.         case MotionEvent.ACTION_UP:  
  23.   
  24.             mStartTouchPoint = null;  
  25.   
  26.             update = moveTrackersIfNeeded(event);  
  27.   
  28.             break;  
  29.   
  30.         }  
  31.   
  32.         if(update){  
  33.   
  34.             if(mListener != null){  
  35.                 mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));  
  36.             }  
  37.   
  38.             invalidate();  
  39.             return true;  
  40.         }  
  41.   
  42.   
  43.         return super.onTouchEvent(event);  
  44.     }  
  45.     //判断是否触发事件,更新区域颜色  
  46.      private boolean moveTrackersIfNeeded(MotionEvent event){  
  47.   
  48.         if(mStartTouchPoint == null) return false;  
  49.   
  50.         boolean update = false;  
  51.         //获取触摸点X,Y坐标值  
  52.         int startX = mStartTouchPoint.x;  
  53.         int startY = mStartTouchPoint.y;  
  54.   
  55.         //判断 X,Y坐标是否在对应的区域内,并做相应的处理   
  56.         if(mHueRect.contains(startX, startY)){  
  57.             mLastTouchedPanel = PANEL_HUE;  
  58.   
  59.             mHue = pointToHue(event.getY());  
  60.   
  61.             update = true;  
  62.         }  
  63.         else if(mSatValRect.contains(startX, startY)){  
  64.   
  65.             mLastTouchedPanel = PANEL_SAT_VAL;  
  66.   
  67.             float[] result = pointToSatVal(event.getX(), event.getY());  
  68.   
  69.             mSat = result[0];  
  70.             mVal = result[1];  
  71.   
  72.             update = true;  
  73.         }  
  74.         else if(mAlphaRect != null && mAlphaRect.contains(startX, startY)){  
  75.   
  76.             mLastTouchedPanel = PANEL_ALPHA;  
  77.   
  78.             mAlpha = pointToAlpha((int)event.getX());  
  79.   
  80.             update = true;  
  81.         }  
  82.   
  83.   
  84.         return update;  
  85.     }  



使用时,让ColorPickerDialog实现ColorPickerView.OnColorChangedListener接口:

并完成对应方法:

  1. @Override  
  2. public void onColorChanged(int color) {  
  3.   
  4.     mNewColor.setColor(color);// mNewColor即为右下角实时显示颜色的ColorPickerPanelView  
  5.       
  6.     if (mHexValueEnabled)  
  7.         updateHexValue(color);  
  8.   
  9.     /* 
  10.     if (mListener != null) { 
  11.         mListener.onColorChanged(color); 
  12.     } 
  13.     */  
  14.   
  15. }  
  1.      private void updateHexValue(int color) {  
  2. if (getAlphaSliderVisible()) {  
  3.     mHexVal.setText(ColorPickerPreference.convertToARGB(color).toUpperCase(Locale.getDefault()));  
  4. else {  
  5.     mHexVal.setText(ColorPickerPreference.convertToRGB(color).toUpperCase(Locale.getDefault()));  
  6. }  
  7. mHexVal.setTextColor(mHexDefaultTextColor);  
  1.      /** 转化为ARGB格式字符串 
  2. * For custom purposes. Not used by ColorPickerPreferrence 
  3. * @param color 
  4. * @author Unknown 
  5. */  
  6.   public static String convertToARGB(int color) {  
  7.       String alpha = Integer.toHexString(Color.alpha(color));  
  8.       String red = Integer.toHexString(Color.red(color));  
  9.       String green = Integer.toHexString(Color.green(color));  
  10.       String blue = Integer.toHexString(Color.blue(color));  
  11.   
  12.       if (alpha.length() == 1) {  
  13.           alpha = "0" + alpha;  
  14.       }  
  15.   
  16.       if (red.length() == 1) {  
  17.           red = "0" + red;  
  18.       }  
  19.   
  20.       if (green.length() == 1) {  
  21.           green = "0" + green;  
  22.       }  
  23.   
  24.       if (blue.length() == 1) {  
  25.           blue = "0" + blue;  
  26.       }  
  27.   
  28.       return "#" + alpha + red + green + blue;  
  29.   }  



最后看一下ColorPickerPanelView点击后的颜色设置事件处理:

  1.        @Override  
  2. public void onClick(View v) {  
  3.     if (v.getId() == R.id.new_color_panel) {  
  4.         if (mListener != null) {  
  5.             mListener.onColorChanged(mNewColor.getColor());  
  6.         }  
  7.     }  
  8.     dismiss();  
  9. }  


注意一下,这里的OnColorChangedListener是在ColorPickerDialog中定义的:

  1.       private OnColorChangedListener mListener;  
  2.   
  3. ublic interface OnColorChangedListener {  
  4. public void onColorChanged(int color);  


最终的颜色是怎么显示到ColorPickerPreference上呢,其实实现的方法是一样的:

  1. implements ColorPickerDialog.OnColorChangedListener  


在ColorPickerPreference中实现对应的回调方法:

  1. @Override  
  2.     public void onColorChanged(int color) {  
  3.         if (isPersistent()) {  
  4.             persistInt(color);  
  5.         }  
  6.         mValue = color;  
  7.         setPreviewColor();  
  8.         try {  
  9.             getOnPreferenceChangeListener().onPreferenceChange(this, color);  
  10.         } catch (NullPointerException e) {  
  11.   
  12.         }  
  13.     }  

调用setPreviewColor()改变ColorPickerPreference中颜色区域的显示:

  1. private void setPreviewColor() {  
  2.         if (mView == null) return;  
  3.         ImageView iView = new ImageView(getContext());  
  4.         LinearLayout widgetFrameView = ((LinearLayout)mView.findViewById(android.R.id.widget_frame));  
  5.         if (widgetFrameView == null) return;  
  6.         widgetFrameView.setVisibility(View.VISIBLE);  
  7.         widgetFrameView.setPadding(  
  8.             widgetFrameView.getPaddingLeft(),  
  9.             widgetFrameView.getPaddingTop(),  
  10.             (int)(mDensity * 8),  
  11.             widgetFrameView.getPaddingBottom()  
  12.         );  
  13.         // remove already create preview image  
  14.         int count = widgetFrameView.getChildCount();  
  15.         if (count > 0) {  
  16.             widgetFrameView.removeViews(0, count);  
  17.         }  
  18.         widgetFrameView.addView(iView);  
  19.         widgetFrameView.setMinimumWidth(0);  
  20.         iView.setBackgroundDrawable(new AlphaPatternDrawable((int)(5 * mDensity)));  
  21.         iView.setImageBitmap(getPreviewBitmap());  
  22.     }  


最后调用getOnPreferenceChangeListener().onPreferenceChange(this, color);改变颜色设置值

然后在下次打开ColorPickerDialog时,传入上面onColorChanged()回调实现中已经改变的mValue参数

  1. mDialog = new ColorPickerDialog(getContext(), mValue);  


至此,PS调色板应用中颜色交互的事件讲解完毕.

相信当分析完PhotoShop调色板应用后,大家会对颜色渲染方面会有一个认识上的提高.

原文地址:https://www.cnblogs.com/Free-Thinker/p/5571868.html