转载请标明位置http://blog.csdn.net/yunmenggyy/article/details/50069209
很久不见了,楼主现在在深圳一家人脸识别技术公司做android开发,接触的是智能硬件方向。毕业到现在,有收获,有迷茫,好在自己终于知道自己想干什么了,哈哈。好了别的就不说了,先看看今天的主题。公司要做一个下拉菜单。效果图如下:
看到这个效果图,首先就得构建思路了,思路很重要!思路很重要!思路很重要!重要的事情说三遍。我的第一反应就是有点像下拉菜单,之前我有仿写过郭霖的下拉菜单,他实现后的效果也是一拉就自动就把头部给拉下来了。那么,假如我们在头部放入这个布局,然后实现下拉的时候根据下拉的距离弹出这个菜单不就行了?楼主也真的这么干了,可是写出来以后发现一个问题。系统的下拉菜单当你拉出来的时候最先看到的是第一行,然后慢慢的会看到第二行,第三行以后后面的内容。但是我的这种实现方式,最先看到的是最底下的内容,其次还是最上面的内容,所以这种方式是不行的!!!!
怎么办?回想既然系统已经实现了这个功能不如去看看系统的源码吧,注意这个源码是位于SystemUI的包下面(我刚开始以为是位于Launcher,结果我找了好久好久都没找到,后来百度一下才知道位于SystemUI的下面),同时还有注意一个问题:android4.3以后的才有下拉菜单,才能点击使得进行快速设置!!接着,我们打开SystemUI的源码,开始寻找自己想要的东西!下面教大家怎么找到自己想要的东西,这个时候有下面几种办法:
a.百度一下,查看一下前辈对SystemUI的布局的介绍;
b.查看布局文件,看看有没有我们想要的。再不然就对照了图标的selector一个一个查找,进而查找到在哪里被用到。
通过上面两个过程,我们就可以找到想要的Java文件,/com.android.systemio.statusbar.phone/PhoneStatusBar.java中,这里不得不说一句抱歉,我找了很久只找到相关的展开函数,而且知道下拉菜单这是一个自定义的PanelView,包含有通知显示以及settings,网上也没发现线索,后来偶然发现它其实是控制Visiable,并动态改变他的大小,这样就可以达到目的了。想想我们平时在开发的时候有没有这种情况,我们把一个View设置为全屏的,刚开始的时候设置为INVISABLE,然后当我们在代码中设置他的属性为VISABLE的时候,他就出现了,而且是全屏出现,试想一下这个时候,假如我们能动态的控制显示高度是不是就可以实现了???试试才知道。
于是乎,重新整合思路。现在我们写一个PopupMenue,我们将自己的自定义控件放入其中,PopUpMenue的背景设成全透明(为什么需要在外面再套一层PopUpMenue?因为我写的自定义的View---->MyDropDownMenue是一个LinearLayout,本身不具备弹出窗口占据窗体的功能,背景设成全透明以后我们在屏幕上就可以直观的看到自己的View)。开始编码。上图这种网格状的布局最好还是用GridView做,这样的话可使图标的状态可知。我之前做的时候做复杂了,这里用的是一个自定义的View,继承自LinearLayout。下面是代码:
/**
* @author GuanGuan
*
*/
public class MyCellLinearLayout extends LinearLayout{
private boolean flag;
private ImageView upImage;
private TextView downText;
private int imageNormal_Id;
private int imagePressed_Id;
private int textSize;
private int normalTextColor =Color.rgb(159, 158, 156);
private int pressedTextColor = Color.rgb(255, 255, 255);
private String text;
private RelativeLayout.LayoutParams layoutPa = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
public MyCellLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init(context,attrs);
}
public MyCellLinearLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
init(context,null);
}
/**
* 初始化数据
*/
private void init(Context context, AttributeSet attrs){
setOrientation(LinearLayout.VERTICAL);
setClickable(true);
if(attrs!=null){
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCellLayout);
imageNormal_Id = a.getResourceId(R.styleable.MyCellLayout_upImage_normal, R.drawable.ic_launcher);
imagePressed_Id = a.getResourceId(R.styleable.MyCellLayout_upImage_pressed, R.drawable.ic_launcher);
text = (String) a.getText(R.styleable.MyCellLayout_downText);
textSize = a.getInteger(R.styleable.MyCellLayout_downTextSize, 25);
a.recycle();
upImage = new ImageView(context);
//upImage.setLayoutParams(layoutPa);
upImage.setImageResource(imageNormal_Id);
downText = new TextView(context);
//downText.setLayoutParams(layoutPa);
downText.setText(text);
downText.setTextSize(textSize);
downText.setTextColor(normalTextColor);
addView(upImage,layoutPa);
layoutPa.topMargin=10;
addView(downText,layoutPa);
layoutPa.topMargin=0;
}
}
/**
* 改变自身的显示状态
*/
public void changeState(){
if(!flag){
upImage.setImageResource(imagePressed_Id);
downText.setTextColor(pressedTextColor);
flag=true;
}else{
upImage.setImageResource(imageNormal_Id);
downText.setTextColor(normalTextColor);
flag=false;
}
}
/**
* 返回当前的命令是打开还是关闭
* @return
*/
public boolean getState(){
return flag;
}
}
用到的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:drop="http://schemas.android.com/apk/res/com.example.test3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#e0000000">
<RelativeLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="60dp">
<TextView
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:text="下午 18:56"
android:textSize="25sp"/>
<ImageView
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/yb100_button_wifi_on"/>
</RelativeLayout>
<!-- the first row -->
<LinearLayout
android:layout_marginTop="152dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.test.MyCellLinearLayout
android:id="@+id/hand"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_hand_off"
drop:upImage_pressed="@drawable/yb100_button_hand_on"
drop:downText="@string/gesture"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/wifi"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_wifi_off"
drop:upImage_pressed="@drawable/yb100_button_wifi_on"
drop:downText="@string/drop_down_menue_wifi"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/upDownWind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_luffing_off"
drop:upImage_pressed="@drawable/yb100_button_luffing_on"
drop:downText="@string/drop_down_menue_updownWind"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/leftRightWind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_swing_off"
drop:upImage_pressed="@drawable/yb100_button_swing_on"
drop:downText="@string/drop_down_menue_lrWind"
drop:downTextSize="25"/>
</LinearLayout>
<!-- the second row -->
<LinearLayout
android:layout_marginTop="76dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.test.MyCellLinearLayout
android:id="@+id/strongWind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_turbo_off"
drop:upImage_pressed="@drawable/yb100_button_turbo_on"
drop:downText="@string/drop_down_menue_strong"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/saveEle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_eco_off"
drop:upImage_pressed="@drawable/yb100_button_eco_on"
drop:downText="@string/drop_down_menue_saveEle"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/clean"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_purify_off"
drop:upImage_pressed="@drawable/yb100_button_purify_on"
drop:downText="@string/drop_down_menue_clean"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/topLight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_light_off"
drop:upImage_pressed="@drawable/yb100_button_light_on"
drop:downText="@string/drop_down_menue_topLoght"
drop:downTextSize="25"/>
</LinearLayout>
<!-- the third row -->
<LinearLayout
android:layout_marginTop="76dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.test.MyCellLinearLayout
android:id="@+id/eleHit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_heat_off"
drop:upImage_pressed="@drawable/yb100_button_heat_on"
drop:downText="@string/drop_down_menue_eleHit"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/autoLight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_autolight_off"
drop:upImage_pressed="@drawable/yb100_button_autolight_on"
drop:downText="@string/drop_down_menue_autoLight"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/quiet"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_quiet_off"
drop:upImage_pressed="@drawable/yb100_button_quiet_on"
drop:downText="@string/drop_down_menue_quite"
drop:downTextSize="25"/>
<com.example.test.MyCellLinearLayout
android:id="@+id/dry_clean"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
drop:upImage_normal="@drawable/yb100_button_dry_off"
drop:upImage_pressed="@drawable/yb100_button_dry_on"
drop:downText="@string/drop_down_menue_dry_clean"
drop:downTextSize="25"/>
</LinearLayout>
<!-- 亮度调节 -->
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/viewMargin"
android:layout_marginTop="118dp" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/system_light" />
<SeekBar
android:id="@+id/seekbar_bright_light"
android:layout_width="620px"
android:layout_height="wrap_content"
android:maxHeight="2dp"
android:minHeight="2dp"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/jianTouMargin"
android:progressDrawable="@drawable/seekbar_bright_style"
android:max="255"
android:thumb="@drawable/seekbar_white_rect"
android:thumbOffset="0dp"
android:progress="100" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/jianTouMargin"
android:src="@drawable/system_bright" />
</RelativeLayout>
<TextView
android:layout_marginTop="101dp"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_marginBottom="1dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:background="@color/setteing_text_color" />
<ImageView
android:id="@+id/setting"
android:layout_gravity="center_horizontal"
android:layout_marginTop="68dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/yb100_function_general"/>
</LinearLayout>
下面是我们的主角:MyDropDownMenue
/**
* @author GuanGuan
* 仿系统下拉菜单的自定义View
*/
public class MyDropDownMenue extends LinearLayout {
private int height=1280-40;
private int measureHeight=40;
private View v;
//first row
private MyCellLinearLayout handControl;
private MyCellLinearLayout wifi;
private MyCellLinearLayout upDownWind;
private MyCellLinearLayout leftRightWind;
//second row
private MyCellLinearLayout strongWind;
private MyCellLinearLayout saveEle;
private MyCellLinearLayout clean;
private MyCellLinearLayout topLight;
//third row
private MyCellLinearLayout eleHit;
private MyCellLinearLayout autoLight;
private MyCellLinearLayout quiet;
private MyCellLinearLayout dry_clean;
private SeekBar mSeekBar;
private ImageView setting;
private OnClickListener mListener;
private Context context;
//private Intent intent = new Intent();
private LinearLayout wholeBac;
private ImageView BacImage;
private Bitmap mBacBitMap;
private Handler hand = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
if (measureHeight <= height ){
measureHeight +=10;
}
break;
case 1:
if(measureHeight-10>0){
measureHeight -=10;
}
if(measureHeight <=10){
SwitchActivity.popWind.dismiss();
}
break;
case 2:
setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, measureHeight));
break;
case 4:
if (mBacBitMap!=null){
v.setBackgroundDrawable(new BitmapDrawable(
Bitmap.createBitmap(mBacBitMap, 0, 0, mBacBitMap.getWidth(), mBacBitMap.getHeight())));
}
break;
default:
break;
}
setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, measureHeight));
invalidate();
}
};
public CopyOfMyDropDownMenue(Context context) {
super(context);
init(context);
}
public CopyOfMyDropDownMenue(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void setScreenWidthH(int width,int height){
this.height =height;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return handEvent(event);
}
public boolean handEvent(MotionEvent event){
int startY=0;
int endY=0;
///往往一个方法觉得不合适(往往只是猜想,没验证,但是找不到其他的方法)
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//setVisibility(View.VISIBLE);
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
endY = (int) event.getRawY();
measureHeight = (endY - startY);
setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, endY));
if(endY<mBacBitMap.getHeight()&&endY>0){
Bitmap bb = Bitmap.createBitmap(mBacBitMap, 0, 0, mBacBitMap.getWidth(), endY);
v.setBackgroundDrawable(new BitmapDrawable(bb));
}else{
v.setBackgroundDrawable(new BitmapDrawable(mBacBitMap));
}
break;
case MotionEvent.ACTION_UP:
if(measureHeight>height/2){
goMove(0);
}else{
goMove(1);
}
break;
default:
break;
}
invalidate();
return true;
}
private void goMove(final int what){
new Thread(new Runnable() {
@Override
public void run() {
try {
if(what ==0){
while(measureHeight<height){
Thread.sleep(5);
Message msg = new Message();
msg.what = what;
hand.sendMessage(msg);
}
if (measureHeight>=height){
if (mBacBitMap!=null){
Message msg = new Message();
msg.what = 4;
hand.sendMessage(msg);
}
}
}else{
while(measureHeight>20){
Thread.sleep(5);
Message msg = new Message();
msg.what = what;
hand.sendMessage(msg);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
//设置
public void setBackgroundBitmap(Bitmap drawable){
mBacBitMap = drawable;
}
/**
* 初始化
*/
private void init(Context context){
this.context = context;
v= View.inflate(context, R.layout.drop_down_menue, null);
wholeBac = (LinearLayout)v.findViewById(R.id.wholeBac);
BacImage = (ImageView) v.findViewById(R.id.BacImage);
mListener = new MyListener();
initComponent(v);
initListener();
setOrientation(LinearLayout.VERTICAL);
addView(v,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
setVisibility(View.GONE);
}
/**
* 初始化组件
* @param view
*/
private void initComponent(View view){
//first row
handControl = (MyCellLinearLayout) view.findViewById(R.id.hand);
wifi = (MyCellLinearLayout) view.findViewById(R.id.wifi);
upDownWind = (MyCellLinearLayout) view.findViewById(R.id.upDownWind);
leftRightWind = (MyCellLinearLayout) view.findViewById(R.id.leftRightWind);
//second row
strongWind = (MyCellLinearLayout) view.findViewById(R.id.strongWind);
saveEle = (MyCellLinearLayout) view.findViewById(R.id.saveEle);
clean = (MyCellLinearLayout) view.findViewById(R.id.clean);
topLight = (MyCellLinearLayout) view.findViewById(R.id.topLight);
//third row
eleHit = (MyCellLinearLayout) view.findViewById(R.id.eleHit);
autoLight = (MyCellLinearLayout) view.findViewById(R.id.autoLight);
quiet = (MyCellLinearLayout) view.findViewById(R.id.quiet);
dry_clean = (MyCellLinearLayout) view.findViewById(R.id.dry_clean);
mSeekBar = (SeekBar) view.findViewById(R.id.seekbar);
setting = (ImageView) view.findViewById(R.id.setting);
}
/**
* 初始化监听器
*/
private void initListener(){
handControl.setOnClickListener(mListener);
wifi.setOnClickListener(mListener);
upDownWind.setOnClickListener(mListener);
leftRightWind.setOnClickListener(mListener);
strongWind.setOnClickListener(mListener);
saveEle.setOnClickListener(mListener);
clean.setOnClickListener(mListener);
topLight.setOnClickListener(mListener);
eleHit.setOnClickListener(mListener);
autoLight.setOnClickListener(mListener);
quiet.setOnClickListener(mListener);
dry_clean.setOnClickListener(mListener);
}
/* public void setOnMenueOpenListener(OnOpenListener listener){
this.listener = listener;
}*/
private final class MyListener implements OnClickListener{
@Override
public void onClick(View v) {
try{
switch (v.getId()) {
//the first row
case R.id.hand:
handControl.changeState();
break;
case R.id.wifi:
wifi.changeState();
break;
case R.id.upDownWind:
upDownWind.changeState();
break;
case R.id.leftRightWind:
leftRightWind.changeState();
break;
//the second Row
case R.id.strongWind:
strongWind.changeState();
break;
case R.id.saveEle:
saveEle.changeState();
break;
case R.id.clean:
clean.changeState();
//airService.clean(clean.getState());
break;
case R.id.topLight:
topLight.changeState();
break;
//the third Row
case R.id.eleHit:
eleHit.changeState();
break;
case R.id.autoLight:
autoLight.changeState();
break;
case R.id.quiet:
quiet.changeState();
break;
case R.id.dry_clean:
dry_clean.changeState();
break;
case R.id.setting:
break;
default:
break;
}
}catch(Exception e){
e.printStackTrace();
}
}
}
/* *//**
* @author 对Menue开关的监听
*
*//*
public static interface OnOpenListener{
public void onOpen();
}*/
}
在Activity中的调用方式为:
private boolean isHeadVisable;
private LinearLayout mExpandView;
private MyDropDownMenue mDropMenue;
private LinearLayout tv;
private int h = 20;
public static PopupWindow popWind;
private Bitmap blurBitmap; //高斯模糊的背景图片
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
int w = getWindowManager().getDefaultDisplay().getWidth();
int h = getWindowManager().getDefaultDisplay().getHeight();
mDropMenue = new MyDropDownMenue(MainActivity.this);
mDropMenue.setLayoutParams(new LayoutParams(w,20));
popWind = new PopupWindow(mDropMenue,w,h);
popWind.setBackgroundDrawable(getResources().getDrawable(R.color.allTouming));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if(event.getRawY()>=20){
mDropMenue.setBackgroundBitmap(blurBitmap);
mDropMenue.setVisibility(View.VISIBLE);
popWind.showAtLocation(getWindow().getDecorView(), Gravity.CENTER, 0, 0);
return mDropMenue.handEvent(event);
}
return super.onTouchEvent(event);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
if (null == blurBitmap){
blurBitmap = fastblur(this, takeScreenShot(this), 25);
Log.e("ceshi","1");
}
}
<span style="white-space:pre"> </span>/**
* 屏幕截图函数
* @param activity 当前的Activity
* @return
*/
private Bitmap takeScreenShot(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay()
.getHeight();
if (b1!=null){
Bitmap b = Bitmap.createBitmap(b1, 0, 0, width, height);
view.destroyDrawingCache();
return b;
}
view.destroyDrawingCache();
return null;
}
//高斯模糊处理,API大于16时候比方法简单些
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) {
if (Build.VERSION.SDK_INT > 16) {
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
final RenderScript rs = RenderScript.create(context);
final Allocation input = Allocation.createFromBitmap(rs, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs, input.getType());
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
script.setRadius(radius /* e.g. 3.f */);
script.setInput(input);
script.forEach(output);
output.copyTo(bitmap);
return bitmap;
}
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
if (radius < 1) {
return (null);
}
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int[] pix = new int[w * h];
Log.e("pix", w + " " + h + " " + pix.length);
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int r[] = new int[wh];
int g[] = new int[wh];
int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
int vmin[] = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
int dv[] = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i / divsum);
}
yw = yi = 0;
int[][] stack = new int[div][3];
int stackpointer;
int stackstart;
int[] sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum;
int rinsum, ginsum, binsum;
for (y = 0; y < h; y++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
sir = stack[i + radius];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rbs = r1 - Math.abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
}
stackpointer = radius;
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
}
p = pix[yw + vmin[x]];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
rbs = r1 - Math.abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
if (i < hm) {
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (x == 0) {
vmin[y] = Math.min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi += w;
}
}
Log.e("pix", w + " " + h + " " + pix.length);
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return (bitmap);
}
}
</pre><pre name="code" class="java">
接下来看看实现的效果: