[转载]ios最新cocos2d-x 3.0博客教学 小游戏[史上最坑爹的游戏] 001主画面以及关卡选择画面的制作 - 移动开发 - eoe移动开发者社区

mikel阅读(905)

[转载]最新cocos2d-x 3.0博客教学 小游戏[史上最坑爹的游戏] 001主画面以及关卡选择画面的制作 – 移动开发 – eoe移动开发者社区.

cocs2d的开发环境我相信大家都能搭建好了,下面我们直接的进入正题,开始做我们的小游戏,如果对搭建环境还有不懂的童鞋请看我写的这篇博文

cocos2d-x 3.0游戏开发xcode5帅印博客教学 001.[HoldTail]环境的搭建以及项目创建

首先我们来看看主画面和关卡选择画面的背景图片

我这里就不上传过多的图片了,直接进入正题看我们的第一个画面如何实现

图片我们是用的原来的官方团对的美术图片在这里大家都要感谢一下官方团体能做出这么美丽的图片(广科院移动应用开发中心)

我这里就不上传过多的图片了,直接进入正题看我们的第一个画面如何实现

主画面由HelloWorldScene.h和HelloWorldScene.cpp构成

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
{
public:
    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::Scene* createScene();
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();

    // a selector callback
    void menuCloseCallback(Object* pSender);

    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp

#include "HelloWorldScene.h"
#include "ScrollViewScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();

    // 'layer' is an autorelease object
    auto layer = HelloWorld::create();
    // add layer as a child to scene
    scene->addChild(layer);
    // return the scene
    return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }

    Size visibleSize = Director::getInstance()->getVisibleSize();
    Point origin = Director::getInstance()->getVisibleOrigin();
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    //加入背景
    Size size = CCDirector::getInstance()->getWinSize();
    SpriteFrameCache *cache = SpriteFrameCache::getInstance();
    cache->addSpriteFramesWithFile("UIResoure.plist");

    Sprite* sprite =Sprite::createWithSpriteFrameName("start-bg.png");
    sprite->setPosition(Point(size.width*0.5+100,size.height*0.5));
    addChild(sprite);

    // add a "close" icon to exit the progress. it's an autorelease object
//    auto closeItem = MenuItemImage::create(
//                                           "UIResoure_play.png",
//                                           "UIResoure_plays.png",
//                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
//    closeItem->setPosition(Point(size.width*0.5,size.height*0.5-100));
//
//    // create menu, it's an autorelease object
//    auto menu = Menu::create(closeItem, NULL);
//    menu->setPosition(Point::ZERO);
//    this->addChild(menu, 1);

    MenuItemImage *closeItem = MenuItemImage::create();
    closeItem->setNormalSpriteFrame(cache->spriteFrameByName("play-1.png"));
    closeItem->setSelectedSpriteFrame(cache->spriteFrameByName("play-2.png"));
    closeItem->initWithTarget(this, menu_selector(HelloWorld::menuCloseCallback));
    closeItem->setPosition(Point(size.width*0.5,size.height*0.5-100));
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Point::ZERO);
    this->addChild(menu, 1);

    return true;
}

void HelloWorld::menuCloseCallback(Object* pSender)
{
    //Director::getInstance()->end();
    //实现
    CCDirector::getInstance()->replaceScene(CCTransitionFade::create(0.5, ScrollViewScene::create()));

    //释放没有用到过的缓冲
    //CCTextureCache::sharedTextureCache()->removeUnusedTextures();
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
//    exit(0);
//#endif
}

这样主画面就做好了,下面进入关卡选择画面的制作,关卡选择画面的制作要比想像中的复杂,首先我们要建立一个场景类

ScrollViewScene.h 和 ScrollViewScene.cpp

ScrollViewScene.h

//
//  ScrollViewScene.h
//  ScrollView
//
//  Created by Tom on 12-6-4.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//
#ifndef ScrollView_ScrollViewScene_h
#define ScrollView_ScrollViewScene_h
#include "cocos2d.h"
USING_NS_CC;
class ScrollViewScene: public Scene
{

public:
    ScrollViewScene();
    virtual bool init();
    CREATE_FUNC(ScrollViewScene);

    void menuCloseCallback(Object* pSender);

    static ScrollViewScene *sharedSC();
};
#endif

ScrollViewScene.cpp

//
//  ScrollViewScene.cpp
//  ScrollView
//
//  Created by Tom on 12-6-4.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//
#include "ScrollViewScene.h"
#include "ScrollView.h"
#include "ScorllMainLayer01.h"
#include "ScorllMainLayer02.h"
#include "ScorllMainLayer03.h"
#include "ScorllMainLayer04.h"
#include "ScorllMainLayer05.h"
#include "ScorllMainLayer06.h"
#include "ScorllMainLayer07.h"
#include "HelloWorldScene.h"
//using namespace CocosDenshion;
//声明静态变量
static ScrollView *scrollView;
static ScrollViewScene *sc;
ScrollViewScene *ScrollViewScene::sharedSC(){
    if(sc != NULL){
        return sc;
    }
    return  NULL;
}
ScrollViewScene::ScrollViewScene()
{

}

bool ScrollViewScene::init()
{
    sc = this;

    bool bRet = false;

    do {
        CC_BREAK_IF(!CCScene::init());
        scrollView = ScrollView::create();

        for (int i=0; i<7; ++i) {
            if (0==i) {
                ScorllMainLayer01 *layer = ScorllMainLayer01::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }else if(1==i){
                ScorllMainLayer02 *layer = ScorllMainLayer02::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }else if(2==i){
                ScorllMainLayer03 *layer = ScorllMainLayer03::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }else if(3==i){
                ScorllMainLayer04 *layer = ScorllMainLayer04::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }else if(4==i){
                ScorllMainLayer05 *layer = ScorllMainLayer05::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }else if(5==i){
                ScorllMainLayer06 *layer = ScorllMainLayer06::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }else if(6==i){
                ScorllMainLayer07 *layer = ScorllMainLayer07::create();
                layer->setTag(i);
                scrollView->addPage(layer);
            }

        }

        Size size = CCDirector::getInstance()->getWinSize();
        //初始化信息
        SpriteFrameCache *cache = SpriteFrameCache::getInstance();
        cache->addSpriteFramesWithFile("level_scene.plist");

        Sprite* spritebg =Sprite::createWithSpriteFrameName("list-bg.png");
        spritebg->setPosition(Point(size.width*0.5+100,size.height*0.5));
        addChild(spritebg);

        //下面的星星
        Sprite* sprite1 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite1->setPosition(Point(size.width*0.5-150,size.height*0.5-200));
        addChild(sprite1);
        Sprite* sprite2 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite2->setPosition(Point(size.width*0.5-100,size.height*0.5-200));
        addChild(sprite2);
        Sprite* sprite3 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite3->setPosition(Point(size.width*0.5-50,size.height*0.5-200));
        addChild(sprite3);
        Sprite* sprite4 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite4->setPosition(Point(size.width*0.5,size.height*0.5-200));
        addChild(sprite4);
        Sprite* sprite5 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite5->setPosition(Point(size.width*0.5+50,size.height*0.5-200));
        addChild(sprite5);
        Sprite* sprite6 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite6->setPosition(Point(size.width*0.5+100,size.height*0.5-200));
        addChild(sprite6);
        Sprite* sprite7 =Sprite::createWithSpriteFrameName("dots-1.png");
        sprite7->setPosition(Point(size.width*0.5+150,size.height*0.5-200));
        addChild(sprite7);

        Sprite* sprite =Sprite::createWithSpriteFrameName("dots-2.png");
        sprite->setPosition(Point(size.width*0.5-150,size.height*0.5-200));
        sprite->setTag(888);
        addChild(sprite);

        MenuItemImage *closeItem = MenuItemImage::create();
        closeItem->setNormalSpriteFrame(cache->spriteFrameByName("back-1.png"));
        closeItem->setSelectedSpriteFrame(cache->spriteFrameByName("back-2.png"));
        closeItem->initWithTarget(this, menu_selector(ScrollViewScene::menuCloseCallback));
        closeItem->setPosition(Point(80,80));

        auto menu = Menu::create(closeItem, NULL);
        menu->setPosition(Point::ZERO);
        this->addChild(menu, 1);

        this->addChild(scrollView);
        bRet = true;
    } while (0);

    return bRet;
}
void ScrollViewScene::menuCloseCallback(Object* pSender){
    CCDirector::getInstance()->replaceScene(CCTransitionFade::create(0.5, HelloWorld::createScene()));
}

建立完成场景类之后,我们要建立我们的场景工具类,这个类可以帮助我们实现左右滑动的效果,这是一个非常用的工具类哦,非常值得大家的学习哦。

ScrollVIew.h 和 ScrollView.cpp

ScrollVIew.h

//
//  ScrollView.h
//  ScrollView
//
//  Created by 帅 印 on 13-8-26.
//  Copyright (c) 2012年 shuaiyinoo. All rights reserved.
//
#ifndef ScrollView_ScrollView_h
#define ScrollView_ScrollView_h
#include "cocos2d.h"
USING_NS_CC;
// 屏幕尺寸
const float WINDOW_WIDTH = 1136.0f;
const float WINDOW_HEIGHT = 640.0f;
// 触摸误差
const int TOUCH_DELTA = 20;
class ScrollView: public Layer
{
private:
    // 按下点
    Point m_TouchDownPoint;
    // 抬起点 配合使用判断是否为点击事件
    Point m_TouchUpPoint;
    // 当前触摸点
    Point m_TouchCurPoint;

private:
    // 总页数
    int m_Page;
    // 当前显示页
    int m_CurPage;

private:
    // 存储所有页层
    Array *m_PageLayer;

private:
    // 跳转页
    void goToPage();

public:
    ScrollView();
    ~ScrollView();

    virtual bool init();

    CREATE_FUNC(ScrollView);
public:
    // 初始化相关
    //virtual void onEnter();
    //virtual void onExit();

    // 触摸事件相关
    bool onTouchBegan(Touch *pTouch, Event  *pEvent);
    void onTouchMoved(Touch *pTouch, Event  *pEvent);
    void onTouchEnded(Touch *pTouch, Event  *pEvent);
    void onTouchCancelled(Touch *pTouch, Event  *pEvent);

public:
    // 添加页
    void addPage(Layer *pPageLayer);
    //公开方法跳转页面
    void gotoUserChoosePage(int _isToOrBack);
};
#endif

ScrollView.cpp

//
//  ScrollView.cpp
//  ScrollView
//
//  Created by 帅 印 on 13-8-26.
//  Copyright (c) 2012年 shuaiyinoo. All rights reserved.
//
#include "ScrollView.h"
#include "ScrollViewScene.h"
ScrollView::ScrollView()
{
    m_Page = 0;
    m_CurPage = 0;
    m_PageLayer = CCArray::createWithCapacity(5);
    m_PageLayer->retain();

    init();
}
ScrollView::~ScrollView()
{
    m_PageLayer->removeAllObjects();
    m_PageLayer->release();
}
bool ScrollView::init()
{
    bool bRet = false;

    do {
        CC_BREAK_IF(!CCLayer::init());

        bRet = true;
    } while (0);

    setTouchEnabled(true);
    //设置为单点响应
    setTouchMode(Touch::DispatchMode::ONE_BY_ONE);

    auto myListener = EventListenerTouchOneByOne::create();
    myListener->onTouchBegan = CC_CALLBACK_2(ScrollView::onTouchBegan, this);
    myListener->onTouchMoved = CC_CALLBACK_2(ScrollView::onTouchMoved, this);
    myListener->onTouchEnded = CC_CALLBACK_2(ScrollView::onTouchEnded, this);
    myListener->onTouchCancelled = CC_CALLBACK_2(ScrollView::onTouchCancelled, this);

    return bRet;
}
//void ScrollView::onEnter()
//{
//    CCLayer::onEnter();
//    //CCDirector::sharedDirector()->getInstance()->addTargetedDelegate(this, 0, true);
//}
//
//void ScrollView::onExit()
//{
//    //CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
//    CCLayer::onExit();
//}
void ScrollView::goToPage()
{
    MoveTo *moveTo = MoveTo::create(0.2f, Point::Point(-m_CurPage * WINDOW_WIDTH, 0));

    this->runAction(moveTo);
}
void ScrollView::addPage(cocos2d::Layer *pPageLayer)
{
    if (pPageLayer) {
        // 设置成一页大小
        pPageLayer->setContentSize(Size::Size(WINDOW_WIDTH, WINDOW_HEIGHT));
        pPageLayer->setPosition(Point(WINDOW_WIDTH * m_Page, 0));
        this->addChild(pPageLayer);
        // 添加到页
        m_PageLayer->addObject(pPageLayer);
        m_Page = m_PageLayer->count();
    }
}
//公开方法进行页面跳转
void ScrollView::gotoUserChoosePage(int _isToOrBack){
    if (0 == _isToOrBack) {
        //上一页
        if (m_CurPage > 0) {
            --m_CurPage;
        }
    }else if(1 == _isToOrBack){
        //下一页
        if (m_CurPage < (m_Page - 1)) {
            ++m_CurPage;
        }
    }

    // 执行跳转动画
    goToPage();
}
bool ScrollView::onTouchBegan(Touch *pTouch, Event  *pEvent){
    m_TouchDownPoint = CCDirector::getInstance()->convertToGL(pTouch->getLocationInView());
    m_TouchCurPoint = m_TouchDownPoint;

    return true;
}
void ScrollView::onTouchMoved(Touch *pTouch, Event  *pEvent){
    // 移动
    Point touchPoint = CCDirector::getInstance()->convertToGL(pTouch->getLocationInView());
    Point posPoint = Point::Point(getPositionX() + touchPoint.x - m_TouchCurPoint.x, getPositionY());
    setPosition(posPoint);
    m_TouchCurPoint = touchPoint;
}
void ScrollView::onTouchEnded(Touch *pTouch, Event  *pEvent){
    m_TouchUpPoint = CCDirector::getInstance()->convertToGL(pTouch->getLocationInView());
    // 计算按下和抬起的偏移量
    float offset = (m_TouchUpPoint.x - m_TouchDownPoint.x) * (m_TouchUpPoint.x - m_TouchDownPoint.x) + (m_TouchUpPoint.y - m_TouchDownPoint.y) * (m_TouchUpPoint.y - m_TouchDownPoint.y);

    if (offset < (TOUCH_DELTA * TOUCH_DELTA)) {
        // 点击
        // 向子Layer发送Click消息
        //((CCLayer*) m_PageLayer->objectAtIndex(m_CurPage))->ccTouchBegan(pTouch, pEvent);
    }
    else {
        // 滑动结束
        int offset = getPositionX() - m_CurPage * (-WINDOW_WIDTH);
        //if (offset > WINDOW_WIDTH / 2) {
        if (offset > 50) {
            // 上一页
            if (m_CurPage > 0) {
                --m_CurPage;
                Sprite *sprite =  (Sprite *)ScrollViewScene::sharedSC()->getChildByTag(888);
                sprite->setPosition(Point(sprite->getPositionX()-50,sprite->getPositionY()));
            }
        }
        //else if (offset < -WINDOW_WIDTH / 2) {
        else if (offset < -50) {
            // 下一页
            if (m_CurPage < (m_Page - 1)) {
                ++m_CurPage;
                Sprite *sprite =  (Sprite *)ScrollViewScene::sharedSC()->getChildByTag(888);
                sprite->setPosition(Point(sprite->getPositionX()+50,sprite->getPositionY()));
            }
        }

        // 执行跳转动画
        goToPage();
    }
}
void ScrollView::onTouchCancelled(Touch *pTouch, Event  *pEvent){

}

下面就是建立不同的场景这样就可以实现场景的切换和关卡的选择了,场景一共有7个我就只带大家创建一个哈

ScorllMainLayer01.h 和 ScorllMainLayer01.cpp

ScorllMainLayer01.h

//
//  ScorllMainLayer01.h
//  Holdtail
//
//  Created by 帅 印 on 13-8-26.
//
//
#ifndef __Holdtail__ScorllMainLayer01__
#define __Holdtail__ScorllMainLayer01__
#include <iostream>
#include "cocos2d.h"
USING_NS_CC;
class ScorllMainLayer01: public Layer
{
public:
    ScorllMainLayer01();
    ~ScorllMainLayer01();

    virtual bool init();

    CREATE_FUNC(ScorllMainLayer01);

    void menuCloseCallback01(Object* pSender);
    void menuCloseCallback02(Object* pSender);
    void menuCloseCallback03(Object* pSender);
    void menuCloseCallback04(Object* pSender);

};
#endif /* defined(__Holdtail__ScorllMainLayer0101__) */

ScorllMainLayer01.cpp

//
//  ScorllMainLayer01.cpp
//  Holdtail
//
//  Created by 帅 印 on 13-8-26.
//
//
#include "ScorllMainLayer01.h"
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
ScorllMainLayer01::ScorllMainLayer01()
{
}
ScorllMainLayer01::~ScorllMainLayer01()
{
}
bool ScorllMainLayer01::init()
{
    bool bRet = false;

    do {
        Size size = CCDirector::getInstance()->getWinSize();
        //初始化信息
        SpriteFrameCache *cache = SpriteFrameCache::getInstance();
        cache->addSpriteFramesWithFile("level_image.plist");

        MenuItemImage *closeItem01 = MenuItemImage::create();
        closeItem01->setNormalSpriteFrame(cache->spriteFrameByName("shutdown-pc-cover.png"));
        closeItem01->setSelectedSpriteFrame(cache->spriteFrameByName("shutdown-pc-cover.png"));
        closeItem01->initWithTarget(this, menu_selector(ScorllMainLayer01::menuCloseCallback01));
        closeItem01->setPosition(Point(size.width*0.5-150,size.height*0.5+200));

        MenuItemImage *closeItem02 = MenuItemImage::create();
        closeItem02->setNormalSpriteFrame(cache->spriteFrameByName("clickon-the-100times-cover.png"));
        closeItem02->setSelectedSpriteFrame(cache->spriteFrameByName("clickon-the-100times-cover.png"));
        closeItem02->initWithTarget(this, menu_selector(ScorllMainLayer01::menuCloseCallback02));
        closeItem02->setPosition(Point(size.width*0.5+150,size.height*0.5+200));

        MenuItemImage *closeItem03 = MenuItemImage::create();
        closeItem03->setNormalSpriteFrame(cache->spriteFrameByName("through-the-bridge-cover.png"));
        closeItem03->setSelectedSpriteFrame(cache->spriteFrameByName("through-the-bridge-cover.png"));
        closeItem03->initWithTarget(this, menu_selector(ScorllMainLayer01::menuCloseCallback03));
        closeItem03->setPosition(Point(size.width*0.5-150,size.height*0.5));

        MenuItemImage *closeItem04 = MenuItemImage::create();
        closeItem04->setNormalSpriteFrame(cache->spriteFrameByName("click-me-cover.png"));
        closeItem04->setSelectedSpriteFrame(cache->spriteFrameByName("click-me-cover.png"));
        closeItem04->initWithTarget(this, menu_selector(ScorllMainLayer01::menuCloseCallback04));
        closeItem04->setPosition(Point(size.width*0.5+150,size.height*0.5));

        auto menu = Menu::create(closeItem01,closeItem02,closeItem03,closeItem04, NULL);
        menu->setPosition(Point::ZERO);
        this->addChild(menu, 1);

        bRet = true;
    } while (0);

    return bRet;
}
void ScorllMainLayer01::menuCloseCallback01(Object* pSender){
    log("SS");
}
void ScorllMainLayer01::menuCloseCallback02(Object* pSender){

}
void ScorllMainLayer01::menuCloseCallback03(Object* pSender){

}
void ScorllMainLayer01::menuCloseCallback04(Object* pSender){

}

这样下来只要你自己再写6个这样的类,我们的游戏主画面跟场景就算是做好了,大家一起加油把。

这里我强调一下由于是用的官方团队的原图片,源码我就暂时不公布出来,如果大家想要,我会联系官方团队后再开源出来,方便大家学习。

[转载]cannot be cast to android.widget.HeaderViewListAdapter_leige87_百度空间

mikel阅读(927)

[转载]cannot be cast to android.widget.HeaderViewListAdapter_leige87_百度空间.

用listview设置header或footerview,通常发生该异常。

如果你没有发生,那是碰巧。但是你可能不知道原因。

如果在listview.setAdapter(adapter)方法之后 添加头或尾view,

即addHeaderView或 addFooterView,

那么在你listView.removeHearderView或removeFooterView时就会报该异常。

在Listview的源码中如果设置了adapter,那么它会强转成HeaderViewListAdapter,所以就会报错。

if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeHeader(v)) {
if (mDataSetObserver != null) {
mDataSetObserver.onChanged();
}
result = true;
}

所以你一定要在setAdapter之前调用addHeaderView或addFooterVeiw.

[转载]apk 反编译-Android新手入门-eoe Android开发者社区_Android开发论坛

mikel阅读(831)

[转载]apk 反编译-Android新手入门-eoe Android开发者社区_Android开发论坛.

1、反编译器前需要准备以下工具
dex2jar :是将apk中的classes.dex转化成jar文件
jd-gui:  源码查看工具jdgui,是一个反编译工具,可以直接查看反编译后的jar包源代码
apktool: apk反编译生成程序的源代码和图片、XML配置、语言资源等文件
2、操作步骤
   反编译代码

  •    首先将apk文件后缀改为zip并解压,得到其中的classes.dex,它就是java文件编译再通过dx工具打包而成的,将classes.dex复制到dex2jar.bat所在目录文件夹。

          在命令行下定位到dex2jar.bat所在目录,运行
          dex2jar.bat    classes.dex
生成
         classes_dex2jar.jar

  •    然后,进入jdgui文件夹双击jd-gui.exe,打开上面生成的jar包classes_dex2jar.jar,即可看到源代码了,如下图

 

——————————————————————————————————————————————————————————————————————-

 

  •   apk反编译生成程序的源代码和图片、XML配置、语言资源等文件
    apktool是 老外写的《Android-apktool》软件,可以帮助我们把APK反编译,生成程序的源代码和图片、XML配置、语言资源等文件。我们对图片和语言资源等文件修改后,可以再把它们编译打包成APK,签名后就是手机可以安装的本地化/修正版APK了。
  • Android-apktool》软件软件可以访问它的主页下载获得,apktool-1.0.0.tar.bz2和apktool-install-windows-2.1_r01-1.zip两个包都要下。下载后解开,为了方便使用,按作者的推荐把得到的4个文件复制到C:\Windows文件夹里。


这个工具是Java写的,需要你的电脑安装了JRE或者JDK,并在系统环境变量Path里加入java.exe所在路径。

以上准备工作做好后,就可以用它来反编译APK了。

     (假设***.apk放在C盘根目录)

代码片段,双击复制
01
apktool d "C:\***.apk" "C:\***"


(命令行解释:apktool d 要反编译的文件 输出文件夹)

这样,***.apk就被反编译了,输出内容在C:\***文件夹里。

重打包了。还是在cmd命令行里,输入

代码片段,双击复制
01
apktool b  “刚刚解压的文件夹路径”  "C:\***.apk"

 

这个***.apk是没有签名的,所以不能直接装到手机里。签名工具和方法见http://www.hiapk.com/bbs/thread-21261-1-1.html

下载地址:http://www.400gb.com/file/42516023

[转载]Easyui1.32源码翻译--datagrid(数据表格) - Jimmy-Lee - 博客园

mikel阅读(1090)

[转载]Easyui1.32源码翻译–datagrid(数据表格) – Jimmy-Lee – 博客园.

      此前网上有easyui1.25的源码  应该算是比较老的版本  之后又经历了1.26 、 1.3、 1.31、 1.32 、1.33、1.34  1.33开始支持css3 算是又一个转折  但是对于ie来说 1.32 个人用的比较多 赶紧更适用 源码翻译是作者利用几个夜晚时间翻译的  这个表格插件算是源码量最大的 先发布这个 之后会继续把整个easyui的插件翻译完毕:下载该插件翻译源码地址

/**
 * jQuery EasyUI 1.3.2
 * 翻译:qq:1364386878 
 *
 */
(function ($) {

    var grid_body_tr_idindex = 0;
    //获取对象下标
    function getObjectIndex(a, o) {
        for (var i = 0, _3 = a.length; i < _3; i++) {
            if (a[i] == o) {
                return i;
            }
        }
        return -1;
    };
    //根据id取消选择行
    function unSelectedRowsById(a, o, id) {
        if (typeof o == "string") {
            for (var i = 0, rows = a.length; i < rows; i++) {
                if (a[i][o] == id) {
                    a.splice(i, 1);
                    return;
                }
            }
        } else {
            var index = getObjectIndex(a, o);
            if (index != -1) {
                a.splice(index, 1);
            }
        }
    };
    //返回标识字段列
    function idFieldRows(scRows, idfield, row) {
        for (var i = 0, rlength = scRows.length; i < rlength; i++) {
            if (scRows[i][idfield] == row[idfield]) {
                return;
            }
        }
        scRows.push(row);
    };
    //做调整和布局
    function _resize(target, parm) {
        var opts = $.data(target, "datagrid").options;
        var panel = $.data(target, "datagrid").panel;
        if (parm) {
            if (parm.width) {
                opts.width = parm.width;
            }
            if (parm.height) {
                opts.height = parm.height;
            }
        }
        if (opts.fit == true) {
            var p = panel.panel("panel").parent();
            opts.width = p.width();
            opts.height = p.height();
        }
        panel.panel("resize", { width: opts.width, height: opts.height });
    };
    //适应大小
    function _fitGridSize(jq) {
        var opts = $.data(jq, "datagrid").options;
        var dc = $.data(jq, "datagrid").dc;
        var panel = $.data(jq, "datagrid").panel;
        var width = panel.width();
        var height = panel.height();
        var gridView = dc.view;
        var gridView1 = dc.view1;
        var gridView2 = dc.view2;
        var gridHeader1 = gridView1.children("div.datagrid-header");
        var gridHeader2 = gridView2.children("div.datagrid-header");
        var gridTable1 = gridHeader1.find("table");
        var gridTable2 = gridHeader2.find("table");
        gridView.width(width);
        var innerHeader = gridHeader1.children("div.datagrid-header-inner").show();
        gridView1.width(innerHeader.find("table").width());
        if (!opts.showHeader) {
            innerHeader.hide();
        }
        gridView2.width(width - gridView1._outerWidth());
        gridView1.children("div.datagrid-header,div.datagrid-body,div.datagrid-footer").width(gridView1.width());
        gridView2.children("div.datagrid-header,div.datagrid-body,div.datagrid-footer").width(gridView2.width());
        var hh;
        gridHeader1.css("height", "");
        gridHeader2.css("height", "");
        gridTable1.css("height", "");
        gridTable2.css("height", "");
        hh = Math.max(gridTable1.height(), gridTable2.height());
        gridTable1.height(hh);
        gridTable2.height(hh);
        gridHeader1.add(gridHeader2)._outerHeight(hh);
        if (opts.height != "auto") {
            var fixedHeight = height - gridView2.children("div.datagrid-header")._outerHeight() - gridView2.children("div.datagrid-footer")._outerHeight() - panel.children("div.datagrid-toolbar")._outerHeight();
            panel.children("div.datagrid-pager").each(function () {
                fixedHeight -= $(this)._outerHeight();
            });
            dc.body1.add(dc.body2).children("table.datagrid-btable-frozen").css({ position: "absolute", top: dc.header2._outerHeight() });
            var height = dc.body2.children("table.datagrid-btable-frozen")._outerHeight();
            gridView1.add(gridView2).children("div.datagrid-body").css({ marginTop: height, height: (fixedHeight - height) });
        }
        gridView.height(gridView2.height());
    };

    //固定指定列高度。如果'index'参数未配置,所有行高度都是固定的
    function _fixRowHeight(target, index, _21) {
        var rows = $.data(target, "datagrid").data.rows;
        var opts = $.data(target, "datagrid").options;
        var dc = $.data(target, "datagrid").dc;
        if (!dc.body1.is(":empty") && (!opts.nowrap || opts.autoRowHeight || _21)) {
            if (index != undefined) {
                var tr1 = opts.finder.getTr(target, index, "body", 1);
                var tr2 = opts.finder.getTr(target, index, "body", 2);
                alignRowHeight(tr1, tr2);
            } else {
                var tr1 = opts.finder.getTr(target, 0, "allbody", 1);
                var tr2 = opts.finder.getTr(target, 0, "allbody", 2);
                alignRowHeight(tr1, tr2);
                if (opts.showFooter) {
                    var tr1 = opts.finder.getTr(target, 0, "allfooter", 1);
                    var tr2 = opts.finder.getTr(target, 0, "allfooter", 2);
                    alignRowHeight(tr1, tr2);
                }
            }
        }
        _fitGridSize(target);
        if (opts.height == "auto") {
            var gridBody1 = dc.body1.parent();
            var gridBody2 = dc.body2;
            var fullHeight = 0;
            var width = 0;
            gridBody2.children().each(function () {
                var c = $(this);
                if (c.is(":visible")) {
                    fullHeight += c._outerHeight();
                    if (width < c._outerWidth()) {
                        width = c._outerWidth();
                    }
                }
            });
            if (width > gridBody2.width()) {
                fullHeight += 18;
            }
            gridBody1.height(fullHeight);
            gridBody2.height(fullHeight);
            dc.view.height(dc.view2.height());
        }
        dc.body2.triggerHandler("scroll");
        function alignRowHeight(target1, target2) {
            for (var i = 0; i < target2.length; i++) {
                var tr1 = $(target1[i]);
                var tr2 = $(target2[i]);
                tr1.css("height", "");
                tr2.css("height", "");
                var height = Math.max(tr1.height(), tr2.height());
                tr1.css("height", height);
                tr2.css("height", height);
            }
        };
    };

    //冻结指定行,当数据表格表格向下滚动的时候始终保持被冻结的行显示在顶部
    function _freezeRow(target, index) {
        var datagrid = $.data(target, "datagrid");
        var opts = datagrid.options;
        var dc = datagrid.dc;
        if (!dc.body2.children("table.datagrid-btable-frozen").length) {
            dc.body1.add(dc.body2).prepend("<table class=\"datagrid-btable datagrid-btable-frozen\" cellspacing=\"0\" cellpadding=\"0\"></table>");
        }
        getfreeze_RowCells(true);
        getfreeze_RowCells(false);
        _fitGridSize(target);
        function getfreeze_RowCells(freezeColmuns) {
            
            var step = freezeColmuns ? 1 : 2;
            var tr = opts.finder.getTr(target, index, "body", step);
            
            (freezeColmuns ? dc.body1 : dc.body2).children("table.datagrid-btable-frozen").append(tr);
        };
    };

    function wrapGrid(target, rownumber) {
        function getcolumns() {
            var frozencols = [];
            var unfrozencols = [];
            $(target).children("thead").each(function () {
                var opt = $.parser.parseOptions(this, [{ frozen: "boolean" }]);
                $(this).find("tr").each(function () {
                    var cols = [];
                    $(this).find("th").each(function () {
                        var th = $(this);
                        var col = $.extend({}, $.parser.parseOptions(this, ["field", "align", "halign", "order", { sortable: "boolean", checkbox: "boolean", resizable: "boolean" }, { rowspan: "number", colspan: "number", width: "number" }]), { title: (th.html() || undefined), hidden: (th.attr("hidden") ? true : undefined), formatter: (th.attr("formatter") ? eval(th.attr("formatter")) : undefined), styler: (th.attr("styler") ? eval(th.attr("styler")) : undefined), sorter: (th.attr("sorter") ? eval(th.attr("sorter")) : undefined) });
                        if (th.attr("editor")) {
                            var s = $.trim(th.attr("editor"));
                            if (s.substr(0, 1) == "{") {
                                col.editor = eval("(" + s + ")");
                            } else {
                                col.editor = s;
                            }
                        }
                        cols.push(col);
                    });

                    opt.frozen ? frozencols.push(cols) : unfrozencols.push(cols);
                });
            });
            return [frozencols, unfrozencols];
        };

        var gridwrap = $("<div class=\"datagrid-wrap\">" + "<div class=\"datagrid-view\">" + "<div class=\"datagrid-view1\">" + "<div class=\"datagrid-header\">" + "<div class=\"datagrid-header-inner\"></div>" + "</div>" + "<div class=\"datagrid-body\">" + "<div class=\"datagrid-body-inner\"></div>" + "</div>" + "<div class=\"datagrid-footer\">" + "<div class=\"datagrid-footer-inner\"></div>" + "</div>" + "</div>" + "<div class=\"datagrid-view2\">" + "<div class=\"datagrid-header\">" + "<div class=\"datagrid-header-inner\"></div>" + "</div>" + "<div class=\"datagrid-body\"></div>" + "<div class=\"datagrid-footer\">" + "<div class=\"datagrid-footer-inner\"></div>" + "</div>" + "</div>" + "</div>" + "</div>").insertAfter(target);
        gridwrap.panel({ doSize: false });
        gridwrap.panel("panel").addClass("datagrid").bind("_resize", function (e, param) {
            var opts = $.data(target, "datagrid").options;
            if (opts.fit == true || param) {
                _resize(target);
                setTimeout(function () {
                    if ($.data(target, "datagrid")) {
                        _fixColumnSize(target);
                    }
                }, 0);
            }
            return false;
        });
        $(target).hide().appendTo(gridwrap.children("div.datagrid-view"));
        var cc = getcolumns();
        var gridView = gridwrap.children("div.datagrid-view");
        var gridView1 = gridView.children("div.datagrid-view1");
        var gridView2 = gridView.children("div.datagrid-view2");
        return {
            panel: gridwrap,
            frozenColumns: cc[0],
            columns: cc[1],
            dc: {
                view: gridView,
                view1: gridView1,
                view2: gridView2,
                header1: gridView1.children("div.datagrid-header").children("div.datagrid-header-inner"),
                header2: gridView2.children("div.datagrid-header").children("div.datagrid-header-inner"),
                body1: gridView1.children("div.datagrid-body").children("div.datagrid-body-inner"),
                body2: gridView2.children("div.datagrid-body"),
                footer1: gridView1.children("div.datagrid-footer").children("div.datagrid-footer-inner"),
                footer2: gridView2.children("div.datagrid-footer").children("div.datagrid-footer-inner")
            }
        };
    };
    //获取表格数据
    function getGridData(jq) {
        var data = { total: 0, rows: [] };
        var fields = _getColumnFields(jq, true).concat(_getColumnFields(jq, false));

        $(jq).find("tbody tr").each(function () {
            data.total++;
            var col = {};
            for (var i = 0; i < fields.length; i++) {
                col[fields[i]] = $("td:eq(" + i + ")", this).html();
            }
            data.rows.push(col);
        });
        return data;
    };
    //初始化
    function init(jq) {
      
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        var dc = datagrid.dc;
     
        var panel = datagrid.panel;
        panel.panel($.extend({}, opts, {
            id: null,
            doSize: false,
            onResize: function (width, height) {
                setTimeout(function () {
                    if ($.data(jq, "datagrid")) {
                        _fitGridSize(jq);
                        _fitColumns(jq);
                        opts.onResize.call(panel, width, height);
                    }
                }, 0);
            },
            onExpand: function () {
                _fixRowHeight(jq);
                opts.onExpand.call(panel);
            }
        }));
        datagrid.rowIdPrefix = "datagrid-row-r" + (++grid_body_tr_idindex);
      
        buildGridHeader(dc.header1, opts.frozenColumns, true);
        buildGridHeader(dc.header2, opts.columns, false);
        cellWidth();//设置单元格宽度
        dc.header1.add(dc.header2).css("display", opts.showHeader ? "block" : "none");
        dc.footer1.add(dc.footer2).css("display", opts.showFooter ? "block" : "none");
        if (opts.toolbar) {
            if (typeof opts.toolbar == "string") {
                $(opts.toolbar).addClass("datagrid-toolbar").prependTo(panel);
                $(opts.toolbar).show();
            } else {
                $("div.datagrid-toolbar", panel).remove();
                var tb = $("<div class=\"datagrid-toolbar\"><table cellspacing=\"0\" cellpadding=\"0\"><tr></tr></table></div>").prependTo(panel);
                var tr = tb.find("tr");
                for (var i = 0; i < opts.toolbar.length; i++) {
                    var btn = opts.toolbar[i];
                    if (btn == "-") {
                        $("<td><div class=\"datagrid-btn-separator\"></div></td>").appendTo(tr);
                    } else {
                        var td = $("<td></td>").appendTo(tr);
                        var tool = $("<a href=\"javascript:void(0)\"></a>").appendTo(td);
                        tool[0].onclick = eval(btn.handler || function () {
                        });
                        tool.linkbutton($.extend({}, btn, { plain: true }));
                    }
                }
            }
        } else {
            $("div.datagrid-toolbar", panel).remove();
        }
        $("div.datagrid-pager", panel).remove();
        if (opts.pagination) {
            var pager = $("<div class=\"datagrid-pager\"></div>");
            if (opts.pagePosition == "bottom") {
                pager.appendTo(panel);
            } else {
                if (opts.pagePosition == "top") {
                    pager.addClass("datagrid-pager-top").prependTo(panel);
                } else {
                    var pagertop = $("<div class=\"datagrid-pager datagrid-pager-top\"></div>").prependTo(panel);
                    pager.appendTo(panel);
                    pager = pager.add(pagertop);
                }
            }
            //分页
            pager.pagination({
                total: 0,
                pageNumber: opts.pageNumber,
                pageSize: opts.pageSize,
                pageList: opts.pageList,
                onSelectPage: function (pageNumber, pageSize) {
                    opts.pageNumber = pageNumber;
                    opts.pageSize = pageSize;
                    pager.pagination("refresh", { pageNumber: pageNumber, pageSize: pageSize });
                    _load(jq);
                }
            });
            opts.pageSize = pager.pagination("options").pageSize;
        }
        function buildGridHeader(headerDiv, clomuns, frozen) {
           
            if (!clomuns) {
                return;
            }
            $(headerDiv).show();
            $(headerDiv).empty();
            var t = $("<table class=\"datagrid-htable\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tbody></tbody></table>").appendTo(headerDiv);
            for (var i = 0; i < clomuns.length; i++) {
                var tr = $("<tr class=\"datagrid-header-row\"></tr>").appendTo($("tbody", t));
                var column = clomuns[i];
                for (var j = 0; j < column.length; j++) {
                    var col = column[j];
                    var tdHTML = "";
                    if (col.rowspan) {
                        tdHTML += "rowspan=\"" + col.rowspan + "\" ";
                    }
                    if (col.colspan) {
                        tdHTML += "colspan=\"" + col.colspan + "\" ";
                    }
                    var td = $("<td " + tdHTML + "></td>").appendTo(tr);
                    if (col.checkbox) {
                        td.attr("field", col.field);
                        $("<div class=\"datagrid-header-check\"></div>").html("<input type=\"checkbox\"/>").appendTo(td);
                    } else {
                        if (col.field) {
                            td.attr("field", col.field);
                            td.append("<div class=\"datagrid-cell\"><span></span><span class=\"datagrid-sort-icon\"></span></div>");
                            $("span", td).html(col.title);
                            $("span.datagrid-sort-icon", td).html("&nbsp;");
                            var cell = td.find("div.datagrid-cell");
                            if (col.resizable == false) {
                                cell.attr("resizable", "false");
                            }
                            if (col.width) {
                                cell._outerWidth(col.width);
                                col.boxWidth = parseInt(cell[0].style.width);
                            } else {
                                col.auto = true;
                            }
                            cell.css("text-align", (col.halign || col.align || ""));
                            col.cellClass = "datagrid-cell-c" + grid_body_tr_idindex + "-" + col.field.replace(/\./g, "-");
                            col.cellSelector = "div." + col.cellClass;
                        } else {
                            $("<div class=\"datagrid-cell-group\"></div>").html(col.title).appendTo(td);
                        }
                    }
                    if (col.hidden) {
                        td.hide();
                    }
                }
            }
            if (frozen && opts.rownumbers) {
                var td = $("<td rowspan=\"" + opts.frozenColumns.length + "\"><div class=\"datagrid-header-rownumber\"></div></td>");
                if ($("tr", t).length == 0) {
                    td.wrap("<tr class=\"datagrid-header-row\"></tr>").parent().appendTo($("tbody", t));
                } else {
                    td.prependTo($("tr:first", t));
                }
            }
        };
        //设置单元格宽度
        function cellWidth() {
            var ss = ["<style type=\"text/css\">"];
            var clomuns = _getColumnFields(jq, true).concat(_getColumnFields(jq));
            for (var i = 0; i < clomuns.length; i++) {
                var col = _getColumnOption(jq, clomuns[i]);
                if (col && !col.checkbox) {
                    ss.push(col.cellSelector + " {width:" + col.boxWidth + "px;}");
                }
            }
            ss.push("</style>");
            $(ss.join("\n")).prependTo(dc.view);
        };
    };
    //绑定事件
    function bingEvent(jq) {
        var datagrid = $.data(jq, "datagrid");
        var panel = datagrid.panel;
        var opts = datagrid.options;
        var dc = datagrid.dc;
        var headinner = dc.header1.add(dc.header2);
        //点击checkbox事件
        headinner.find("input[type=checkbox]").unbind(".datagrid").bind("click.datagrid", function (e) {
           
            if (opts.singleSelect && opts.selectOnCheck) {
                return false;
            }
            if ($(this).is(":checked")) {
                _checkAll(jq);
            } else {
                _clearChecked(jq);
            }
            e.stopPropagation();
        });
        var gridcell = headinner.find("div.datagrid-cell");
       //鼠标进入标题单元格事件
        gridcell.closest("td").unbind(".datagrid").bind("mouseenter.datagrid", function () {         
            if (datagrid.resizing) {
                return;
            }
            $(this).addClass("datagrid-header-over");
        }).bind("mouseleave.datagrid", function () { //鼠标离开标题事件
            $(this).removeClass("datagrid-header-over");
        }).bind("contextmenu.datagrid", function (e) {//鼠标右键标题事件
        
            var field = $(this).attr("field");
            opts.onHeaderContextMenu.call(jq, e, field);
        });
        //点击titl事件
        gridcell.unbind(".datagrid").bind("click.datagrid", function (e) {
          
            var p1 = $(this).offset().left + 5;
            var p2 = $(this).offset().left + $(this)._outerWidth() - 5;
            if (e.pageX < p2 && e.pageX > p1) {
                var field = $(this).parent().attr("field");
                var col = _getColumnOption(jq, field);////返回指定列属性
                if (!col.sortable || datagrid.resizing) {
                    return;
                }
                opts.sortName = field;
                opts.sortOrder = col.order || "asc";
                var cls = "datagrid-sort-" + opts.sortOrder;
                if ($(this).hasClass("datagrid-sort-asc")) {
                    cls = "datagrid-sort-desc";
                    opts.sortOrder = "desc";
                } else {
                    if ($(this).hasClass("datagrid-sort-desc")) {
                        cls = "datagrid-sort-asc";
                        opts.sortOrder = "asc";
                    }
                }
                gridcell.removeClass("datagrid-sort-asc datagrid-sort-desc");
                $(this).addClass(cls);
                if (opts.remoteSort) {
                    _load(jq);
                } else {
                    var data = $.data(jq, "datagrid").data;
                    _removeData(jq, data);
                }
                opts.onSortColumn.call(jq, opts.sortName, opts.sortOrder);
            }
        }).bind("dblclick.datagrid", function (e) {//双击事件
            var p1 = $(this).offset().left + 5;
            var p2 = $(this).offset().left + $(this)._outerWidth() - 5;
            var resizeHandle = opts.resizeHandle == "right" ? (e.pageX > p2) : (opts.resizeHandle == "left" ? (e.pageX < p1) : (e.pageX < p1 || e.pageX > p2));
            
            if (resizeHandle) {
                var field = $(this).parent().attr("field");
                var col = _getColumnOption(jq, field);
                if (col.resizable == false) {
                    return;
                }
                $(jq).datagrid("autoSizeColumn", field);
                col.auto = false;
            }
        });
        var resizeHandle = opts.resizeHandle == "right" ? "e" : (opts.resizeHandle == "left" ? "w" : "e,w");
        gridcell.each(function () {
            $(this).resizable({
                handles: resizeHandle,
                disabled: ($(this).attr("resizable") ? $(this).attr("resizable") == "false" : false),
                minWidth: 25,
                onStartResize: function (e) {
                    datagrid.resizing = true;
                    headinner.css("cursor", $("body").css("cursor"));
                    if (!datagrid.proxy) {
                        datagrid.proxy = $("<div class=\"datagrid-resize-proxy\"></div>").appendTo(dc.view);
                    }
                    datagrid.proxy.css({ left: e.pageX - $(panel).offset().left - 1, display: "none" });
                    setTimeout(function () {
                        if (datagrid.proxy) {
                            datagrid.proxy.show();
                        }
                    }, 500);
                },
                onResize: function (e) {
                    datagrid.proxy.css({ left: e.pageX - $(panel).offset().left - 1, display: "block" });
                    return false;
                },
                onStopResize: function (e) {
                    headinner.css("cursor", "");
                    var field = $(this).parent().attr("field");
                    var col = _getColumnOption(jq, field);
                    col.width = $(this)._outerWidth();
                    col.boxWidth = parseInt(this.style.width);
                    col.auto = undefined;
                    _fixColumnSize(jq, field);
                    datagrid.proxy.remove();
                    datagrid.proxy = null;
                    if ($(this).parents("div:first.datagrid-header").parent().hasClass("datagrid-view1")) {
                        _fitGridSize(jq);
                    }
                    _fitColumns(jq);
                    opts.onResizeColumn.call(jq, field, col.width);
                    setTimeout(function () {
                        datagrid.resizing = false;
                    }, 0);
                }
            });
        });
        //grid body 鼠标进入事件
        dc.body1.add(dc.body2).unbind().bind("mouseover", function (e) {
            
            if (datagrid.resizing) {
                return;
            }
            var tr = $(e.target).closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            var index = get_trIndex(tr);           
            opts.finder.getTr(jq, index).addClass("datagrid-row-over");
            e.stopPropagation();
        }).bind("mouseout", function (e) { //grid body 鼠标移出事件
            var tr = $(e.target).closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            var index = get_trIndex(tr);
            opts.finder.getTr(jq, index).removeClass("datagrid-row-over");
            e.stopPropagation();
        }).bind("click", function (e) { //grid body 鼠标点击事件           
            var tt = $(e.target);
            var tr = tt.closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            var index = get_trIndex(tr);
            if (tt.parent().hasClass("datagrid-cell-check")) {
                if (opts.singleSelect && opts.selectOnCheck) {
                    if (!opts.checkOnSelect) {
                        _clearChecked(jq, true);
                    }
                    _checkRow(jq, index);
                } else {
                    if (tt.is(":checked")) {
                        _checkRow(jq, index);
                    } else {
                        _uncheckRow(jq, index);
                    }
                }
            } else {
                var row = opts.finder.getRow(jq, index);
                var td = tt.closest("td[field]", tr);
                if (td.length) {
                    var _6f = td.attr("field");
                    opts.onClickCell.call(jq, index, _6f, row[_6f]);
                }
                if (opts.singleSelect == true) {
                    _selectRow(jq, index);
                } else {
                    if (tr.hasClass("datagrid-row-selected")) {
                        _unselectRow(jq, index);
                    } else {
                        _selectRow(jq, index);
                    }
                }
                opts.onClickRow.call(jq, index, row);
            }
            e.stopPropagation();
        }).bind("dblclick", function (e) {//grid body 鼠标双击事件 
            var tt = $(e.target);
            var tr = tt.closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            var index = get_trIndex(tr);
            var row = opts.finder.getRow(jq, index);
            var td = tt.closest("td[field]", tr);
            if (td.length) {
                var field = td.attr("field");
                opts.onDblClickCell.call(jq, index, field, row[field]);
            }
            opts.onDblClickRow.call(jq, index, row);
            e.stopPropagation();
        }).bind("contextmenu", function (e) {//grid body 鼠标右键事件 
            var tr = $(e.target).closest("tr.datagrid-row");
            if (!tr.length) {
                return;
            }
            var index = get_trIndex(tr);
            var row = opts.finder.getRow(jq, index);
            opts.onRowContextMenu.call(jq, e, index, row);
            e.stopPropagation();
        });
        dc.body2.bind("scroll", function () {//grid body 滚动条事件 
         
            dc.view1.children("div.datagrid-body").scrollTop($(this).scrollTop());
            dc.view2.children("div.datagrid-header,div.datagrid-footer")._scrollLeft($(this)._scrollLeft());
            dc.body2.children("table.datagrid-btable-frozen").css("left", -$(this)._scrollLeft());
        });
        //获取td index
        function get_trIndex(tr) {
            if (tr.attr("datagrid-row-index")) {
                return parseInt(tr.attr("datagrid-row-index"));
            } else {
                return tr.attr("node-id");
            }
        };
    };
    //使列自动展开/收缩到合适的数据表格宽度
    function _fitColumns(jq) {
        var opts = $.data(jq, "datagrid").options;
        var dc = $.data(jq, "datagrid").dc;
        if (!opts.fitColumns) {
            return;
        }
        var header = dc.view2.children("div.datagrid-header");
        var visableWidth = 0;
        var visableColumn;
        var fields = _getColumnFields(jq, false);
        for (var i = 0; i < fields.length; i++) {
            var col = _getColumnOption(jq, fields[i]);
            if (_7a(col)) {
                visableWidth += col.width;
                visableColumn = col;
            }
        }
        var innerHeader = header.children("div.datagrid-header-inner").show();
        var fullWidth = header.width() - header.find("table").width() - opts.scrollbarSize;
        var rate = fullWidth / visableWidth;
        if (!opts.showHeader) {
            innerHeader.hide();
        }
        for (var i = 0; i < fields.length; i++) {
            var col = _getColumnOption(jq, fields[i]);
            if (_7a(col)) {
                var width = Math.floor(col.width * rate);
                fitColumnWidth(col, width);
                fullWidth -= width;
            }
        }
        if (fullWidth && visableColumn) {
            fitColumnWidth(visableColumn, fullWidth);
        }
        _fixColumnSize(jq);
        function fitColumnWidth(col, _80) {
            col.width += _80;
            col.boxWidth += _80;
            header.find("td[field=\"" + col.field + "\"] div.datagrid-cell").width(col.boxWidth);
        };
        function _7a(col) {
            if (!col.hidden && !col.checkbox && !col.auto) {
                return true;
            }
        };
    };
    //自动调整列宽度以适应内容
    function _autoSizeColumn(jq, filed) {
        var opts = $.data(jq, "datagrid").options;
        var dc = $.data(jq, "datagrid").dc;
        if (filed) {
            _resize(filed);
            if (opts.fitColumns) {
                _fitGridSize(jq);
                _fitColumns(jq);
            }
        } else {
            var _85 = false;
            var _86 = _getColumnFields(jq, true).concat(_getColumnFields(jq, false));
            for (var i = 0; i < _86.length; i++) {
                var filed = _86[i];
                var col = _getColumnOption(jq, filed);
                if (col.auto) {
                    _resize(filed);
                    _85 = true;
                }
            }
            if (_85 && opts.fitColumns) {
                _fitGridSize(jq);
                _fitColumns(jq);
            }
        }
        function _resize(_87) {
            var _88 = dc.view.find("div.datagrid-header td[field=\"" + _87 + "\"] div.datagrid-cell");
            _88.css("width", "");
            var col = $(jq).datagrid("getColumnOption", _87);
            col.width = undefined;
            col.boxWidth = undefined;
            col.auto = true;
            $(jq).datagrid("fixColumnSize", _87);
            var _89 = Math.max(_88._outerWidth(), _8a("allbody"), _8a("allfooter"));
            _88._outerWidth(_89);
            col.width = _89;
            col.boxWidth = parseInt(_88[0].style.width);
            $(jq).datagrid("fixColumnSize", _87);
            opts.onResizeColumn.call(jq, _87, col.width);
            function _8a(_8b) {
                var _8c = 0;
                opts.finder.getTr(jq, 0, _8b).find("td[field=\"" + _87 + "\"] div.datagrid-cell").each(function () {
                    var w = $(this)._outerWidth();
                    if (_8c < w) {
                        _8c = w;
                    }
                });
                return _8c;
            };
        };
    };
    //固定列大小。如果'field'参数未配置,所有列大小将都是固定的
    function _fixColumnSize(jq, field) {
        var opts = $.data(jq, "datagrid").options;
        var dc = $.data(jq, "datagrid").dc;
        var vtable = dc.view.find("table.datagrid-btable,table.datagrid-ftable");
        vtable.css("table-layout", "fixed");
        if (field) {
            fix(field);
        } else {
            var ff = _getColumnFields(jq, true).concat(_getColumnFields(jq, false));
            for (var i = 0; i < ff.length; i++) {
                fix(ff[i]);
            }
        }
        vtable.css("table-layout", "auto");
        _91(jq);
        setTimeout(function () {
            _fixRowHeight(jq);
            fixEditorSize(jq);
        }, 0);
        function fix(field) {
            var col = _getColumnOption(jq, field);
            if (col.checkbox) {
                return;
            }
            var _93 = dc.view.children("style")[0];
            var _94 = _93.styleSheet ? _93.styleSheet : (_93.sheet || document.styleSheets[document.styleSheets.length - 1]);
            var _95 = _94.cssRules || _94.rules;
            for (var i = 0, len = _95.length; i < len; i++) {
                var _96 = _95[i];
                if (_96.selectorText.toLowerCase() == col.cellSelector.toLowerCase()) {
                    _96.style["width"] = col.boxWidth ? col.boxWidth + "px" : "auto";
                    break;
                }
            }
        };
    };
    function _91(jq) {
        var dc = $.data(jq, "datagrid").dc;
        dc.body1.add(dc.body2).find("td.datagrid-td-merged").each(function () {
            var td = $(this);
            var colspan = td.attr("colspan") || 1;
            var width = _getColumnOption(jq, td.attr("field")).width;
            for (var i = 1; i < colspan; i++) {
                td = td.next();
                width += _getColumnOption(jq, td.attr("field")).width + 1;
            }
            $(this).children("div.datagrid-cell")._outerWidth(width);
        });
    };
    function fixEditorSize(_9b) {
        var dc = $.data(_9b, "datagrid").dc;
        dc.view.find("div.datagrid-editable").each(function () {
            var _9c = $(this);
            var _9d = _9c.parent().attr("field");
            var col = $(_9b).datagrid("getColumnOption", _9d);
            _9c._outerWidth(col.width);
            var ed = $.data(this, "datagrid.editor");
            if (ed.actions.resize) {
                ed.actions.resize(ed.target, _9c.width());
            }
        });
    };
    //返回指定列属性
    function _getColumnOption(jq, filed) {
        function _a0(_a1) {
            if (_a1) {
                for (var i = 0; i < _a1.length; i++) {
                    var cc = _a1[i];
                    for (var j = 0; j < cc.length; j++) {
                        var c = cc[j];
                        if (c.field == filed) {
                            return c;
                        }
                    }
                }
            }
            return null;
        };
        var opts = $.data(jq, "datagrid").options;
        var col = _a0(opts.columns);
        if (!col) {
            col = _a0(opts.frozenColumns);
        }
        return col;
    };
    //返回列字段。如果设置了frozen属性为true,将返回固定列的字段名
    function _getColumnFields(jq, frozen) {
        var opts = $.data(jq, "datagrid").options;
        var columns = (frozen == true) ? (opts.frozenColumns || [[]]) : opts.columns;
        if (columns.length == 0) {
            return [];
        }
        var fields = [];
        function getFixedColspan(index) {
            var c = 0;
            var i = 0;
            while (true) {
                if (fields[i] == undefined) {
                    if (c == index) {
                        return i;
                    }
                    c++;
                }
                i++;
            }
        };
        function findColumnFields(r) {
            var ff = [];
            var c = 0;
            for (var i = 0; i < columns[r].length; i++) {
                var col = columns[r][i];
                if (col.field) {
                    ff.push([c, col.field]);
                }
                c += parseInt(col.colspan || "1");
            }
            for (var i = 0; i < ff.length; i++) {
                ff[i][0] = getFixedColspan(ff[i][0]);
            }
            for (var i = 0; i < ff.length; i++) {
                var f = ff[i];
                fields[f[0]] = f[1];
            }
        };
        for (var i = 0; i < columns.length; i++) {
            findColumnFields(i);
        }
        return fields;
    };
    //加载本地数据,旧的行将被移除
    function _removeData(jq, data) {
        var _ae = $.data(jq, "datagrid");
        var _af = _ae.options;
        var dc = _ae.dc;
        data = _af.loadFilter.call(jq, data);
        data.total = parseInt(data.total);
        _ae.data = data;
        if (data.footer) {
            _ae.footer = data.footer;
        }
        if (!_af.remoteSort) {
            var opt = _getColumnOption(jq, _af.sortName);
            if (opt) {
                var _b0 = opt.sorter || function (a, b) {
                    return (a > b ? 1 : -1);
                };
                data.rows.sort(function (r1, r2) {
                    return _b0(r1[_af.sortName], r2[_af.sortName]) * (_af.sortOrder == "asc" ? 1 : -1);
                });
            }
        }
        if (_af.view.onBeforeRender) {
            _af.view.onBeforeRender.call(_af.view, jq, data.rows);
        }
        _af.view.render.call(_af.view, jq, dc.body2, false);
        _af.view.render.call(_af.view, jq, dc.body1, true);
        if (_af.showFooter) {
            _af.view.renderFooter.call(_af.view, jq, dc.footer2, false);
            _af.view.renderFooter.call(_af.view, jq, dc.footer1, true);
        }
        if (_af.view.onAfterRender) {
            _af.view.onAfterRender.call(_af.view, jq);
        }
        dc.view.children("style:gt(0)").remove();
        _af.onLoadSuccess.call(jq, data);
        var _b1 = $(jq).datagrid("getPager");
        if (_b1.length) {
            if (_b1.pagination("options").total != data.total) {
                _b1.pagination("refresh", { total: data.total });
            }
        }
        _fixRowHeight(jq);
        dc.body2.triggerHandler("scroll");
        _b2();
        $(jq).datagrid("autoSizeColumn");
        function _b2() {
            if (_af.idField) {
                for (var i = 0; i < data.rows.length; i++) {
                    var row = data.rows[i];
                    if (_b3(_ae.selectedRows, row)) {
                        _selectRow(jq, i, true);
                    }
                    if (_b3(_ae.checkedRows, row)) {
                        _checkRow(jq, i, true);
                    }
                }
            }
            function _b3(a, r) {
                for (var i = 0; i < a.length; i++) {
                    if (a[i][_af.idField] == r[_af.idField]) {
                        a[i] = r;
                        return true;
                    }
                }
                return false;
            };
        };
    };
    //返回指定行的索引号,该行的参数可以是一行记录或一个ID字段值
    function _getRowIndex(jq, row) {
        var opts = $.data(jq, "datagrid").options;
        var rows = $.data(jq, "datagrid").data.rows;
        if (typeof row == "object") {
            return getObjectIndex(rows, row);
        } else {
            for (var i = 0; i < rows.length; i++) {
                if (rows[i][opts.idField] == row) {
                    return i;
                }
            }
            return -1;
        }
    };
    //返回所有被选中的行,当没有记录被选中的时候将返回一个空数组
    function _getSelected(jq) {
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        var data = datagrid.data;
        if (opts.idField) {
            return datagrid.selectedRows;
        } else {
            var selectRows = [];
            opts.finder.getTr(jq, "", "selected", 2).each(function () {
                var _be = parseInt($(this).attr("datagrid-row-index"));
                selectRows.push(data.rows[_be]);
            });
            return selectRows;
        }
    };
    //在复选框呗选中的时候返回所有行
    function _getChecked(jq) {
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        if (opts.idField) {
            return datagrid.checkedRows;
        } else {
            var checkRows = [];
            datagrid.dc.view.find("div.datagrid-cell-check input:checked").each(function () {
                var _c4 = $(this).closest("tr.datagrid-row").attr("datagrid-row-index");
                checkRows.push(opts.finder.getRow(jq, _c4));
            });
            return checkRows;
        }
    };
    //通过ID值参数选择一行
    function _selectRecord(jq, id) {
        var opts = $.data(jq, "datagrid").options;
        if (opts.idField) {
            var index = _getRowIndex(jq, id);
            if (index >= 0) {
                _selectRow(jq, index);
            }
        }
    };
    //选择一行,行索引从0开始
    function _selectRow(jq, index, _cd) {
        var datagrid = $.data(jq, "datagrid");
        var dc = datagrid.dc;
        var opts = datagrid.options;
        var selectRows = datagrid.selectedRows;
        if (opts.singleSelect) {
            _clearSelections(jq);
            selectRows.splice(0, selectRows.length);
        }
        if (!_cd && opts.checkOnSelect) {
            _checkRow(jq, index, true);
        }
        var row = opts.finder.getRow(jq, index);
        if (opts.idField) {
            idFieldRows(selectRows, opts.idField, row);
        }
        opts.onSelect.call(jq, index, row);
        var tr = opts.finder.getTr(jq, index).addClass("datagrid-row-selected");
        if (tr.length) {
            if (tr.closest("table").hasClass("datagrid-btable-frozen")) {
                return;
            }
            var _d3 = dc.view2.children("div.datagrid-header")._outerHeight();
            var _d4 = dc.body2;
            var _d5 = _d4.outerHeight(true) - _d4.outerHeight();
            var top = tr.position().top - _d3 - _d5;
            if (top < 0) {
                _d4.scrollTop(_d4.scrollTop() + top);
            } else {
                if (top + tr._outerHeight() > _d4.height() - 18) {
                    _d4.scrollTop(_d4.scrollTop() + top + tr._outerHeight() - _d4.height() + 18);
                }
            }
        }
    };
    function _unselectRow(_d7, _d8, _d9) {
        var _da = $.data(_d7, "datagrid");
        var dc = _da.dc;
        var _db = _da.options;
        var _dc = $.data(_d7, "datagrid").selectedRows;
        if (!_d9 && _db.checkOnSelect) {
            _uncheckRow(_d7, _d8, true);
        }
        _db.finder.getTr(_d7, _d8).removeClass("datagrid-row-selected");
        var row = _db.finder.getRow(_d7, _d8);
        if (_db.idField) {
            unSelectedRowsById(_dc, _db.idField, row[_db.idField]);
        }
        _db.onUnselect.call(_d7, _d8, row);
    };
    function _selectAll(_df, _e0) {
        var _e1 = $.data(_df, "datagrid");
        var _e2 = _e1.options;
        var _e3 = _e1.data.rows;
        var _e4 = $.data(_df, "datagrid").selectedRows;
        if (!_e0 && _e2.checkOnSelect) {
            _checkAll(_df, true);
        }
        _e2.finder.getTr(_df, "", "allbody").addClass("datagrid-row-selected");
        if (_e2.idField) {
            for (var _e6 = 0; _e6 < _e3.length; _e6++) {
                idFieldRows(_e4, _e2.idField, _e3[_e6]);
            }
        }
        _e2.onSelectAll.call(_df, _e3);
    };
    function _clearSelections(_e7, _e8) {
        var _e9 = $.data(_e7, "datagrid");
        var _ea = _e9.options;
        var _eb = _e9.data.rows;
        var _ec = $.data(_e7, "datagrid").selectedRows;
        if (!_e8 && _ea.checkOnSelect) {
            _clearChecked(_e7, true);
        }
        _ea.finder.getTr(_e7, "", "selected").removeClass("datagrid-row-selected");
        if (_ea.idField) {
            for (var _ee = 0; _ee < _eb.length; _ee++) {
                unSelectedRowsById(_ec, _ea.idField, _eb[_ee][_ea.idField]);
            }
        }
        _ea.onUnselectAll.call(_e7, _eb);
    };
    //勾选一行 
    function _checkRow(jq, index, state) {
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        if (!state && opts.selectOnCheck) {
            _selectRow(jq, index, true);
        }
        var ck = opts.finder.getTr(jq, index).find("div.datagrid-cell-check input[type=checkbox]");
        ck._propAttr("checked", true);
        ck = opts.finder.getTr(jq, "", "allbody").find("div.datagrid-cell-check input[type=checkbox]:not(:checked)");
        if (!ck.length) {
            var dc = datagrid.dc;
            var _f4 = dc.header1.add(dc.header2);
            _f4.find("input[type=checkbox]")._propAttr("checked", true);
        }
        var row = opts.finder.getRow(jq, index);
        if (opts.idField) {
            idFieldRows(datagrid.checkedRows, opts.idField, row);
        }
        opts.onCheck.call(jq, index, row);
    };
    //取消勾选一行 
    function _uncheckRow(jq, index, state) {
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        if (!state && opts.selectOnCheck) {
            _unselectRow(jq, index, true);
        }
        var ck = opts.finder.getTr(jq, index).find("div.datagrid-cell-check input[type=checkbox]");
        ck._propAttr("checked", false);
        var dc = datagrid.dc;
        var _fa = dc.header1.add(dc.header2);
        _fa.find("input[type=checkbox]")._propAttr("checked", false);
        var row = opts.finder.getRow(jq, index);
        if (opts.idField) {
            unSelectedRowsById(datagrid.checkedRows, opts.idField, row[opts.idField]);
        }
        opts.onUncheck.call(jq, index, row);
    };
    function _checkAll(_fb, _fc) {
        var _fd = $.data(_fb, "datagrid");
        var _fe = _fd.options;
        var _ff = _fd.data.rows;
        if (!_fc && _fe.selectOnCheck) {
            _selectAll(_fb, true);
        }
        var dc = _fd.dc;
        var hck = dc.header1.add(dc.header2).find("input[type=checkbox]");
        var bck = _fe.finder.getTr(_fb, "", "allbody").find("div.datagrid-cell-check input[type=checkbox]");
        hck.add(bck)._propAttr("checked", true);
        if (_fe.idField) {
            for (var i = 0; i < _ff.length; i++) {
                idFieldRows(_fd.checkedRows, _fe.idField, _ff[i]);
            }
        }
        _fe.onCheckAll.call(_fb, _ff);
    };
    function _clearChecked(_100, _101) {
        var _102 = $.data(_100, "datagrid");
        var opts = _102.options;
        var rows = _102.data.rows;
        if (!_101 && opts.selectOnCheck) {
            _clearSelections(_100, true);
        }
        var dc = _102.dc;
        var hck = dc.header1.add(dc.header2).find("input[type=checkbox]");
        var bck = opts.finder.getTr(_100, "", "allbody").find("div.datagrid-cell-check input[type=checkbox]");
        hck.add(bck)._propAttr("checked", false);
        if (opts.idField) {
            for (var i = 0; i < rows.length; i++) {
                unSelectedRowsById(_102.checkedRows, opts.idField, rows[i][opts.idField]);
            }
        }
        opts.onUncheckAll.call(_100, rows);
    };
    //开始编辑行
    function _beginEdit(jq, index) {
        var opts = $.data(jq, "datagrid").options;
        var tr = opts.finder.getTr(jq, index);
        var row = opts.finder.getRow(jq, index);
        if (tr.hasClass("datagrid-row-editing")) {
            return;
        }
        if (opts.onBeforeEdit.call(jq, index, row) == false) {
            return;
        }
        tr.addClass("datagrid-row-editing");
        createEditor(jq, index);
        fixEditorSize(jq);
        tr.find("div.datagrid-editable").each(function () {
            var _107 = $(this).parent().attr("field");
            var ed = $.data(this, "datagrid.editor");
            ed.actions.setValue(ed.target, row[_107]);
        });
        validateRow(jq, index);
    };
    //结束编辑行
    function _endEdit(jq, index, revert) {
        var opts = $.data(jq, "datagrid").options;
        var updatedRows = $.data(jq, "datagrid").updatedRows;
        var insertedRows = $.data(jq, "datagrid").insertedRows;
        var tr = opts.finder.getTr(jq, index);
        var row = opts.finder.getRow(jq, index);
        if (!tr.hasClass("datagrid-row-editing")) {
            return;
        }
        if (!revert) {
            if (!validateRow(jq, index)) {
                return;
            }
            var changed = false;
            var newValues = {};
            tr.find("div.datagrid-editable").each(function () {
                var field = $(this).parent().attr("field");
                var ed = $.data(this, "datagrid.editor");
                var field = ed.actions.getValue(ed.target);
                if (row[field] != field) {
                    row[field] = field;
                    changed = true;
                    newValues[field] = field;
                }
            });
            if (changed) {
                if (getObjectIndex(insertedRows, row) == -1) {
                    if (getObjectIndex(updatedRows, row) == -1) {
                        updatedRows.push(row);
                    }
                }
            }
        }
        tr.removeClass("datagrid-row-editing");
        destroyEditor(jq, index);
        $(jq).datagrid("refreshRow", index);
        if (!revert) {
            opts.onAfterEdit.call(jq, index, row, newValues);
        } else {
            opts.onCancelEdit.call(jq, index, row);
        }
    };
    //获取指定行的编辑器。每个编辑器都有以下属性:
    //actions:编辑器可以执行的动作,同编辑器定义。
    //target:目标编辑器的jQuery对象。
    //field:字段名称。
    //type:编辑器类型,比如:'text','combobox','datebox'等。
    function _getEditors(jq, index) {
        var opts = $.data(jq, "datagrid").options;
        var tr = opts.finder.getTr(jq, index);
        var editors = [];
        tr.children("td").each(function () {
            var cell = $(this).find("div.datagrid-editable");
            if (cell.length) {
                var ed = $.data(cell[0], "datagrid.editor");
                editors.push(ed);
            }
        });
        return editors;
    };
    //获取指定编辑器,options包含2个属性:
    //index:行索引。
    //field:字段名称。
    function _getEditor(jq, options) {
        var editors = _getEditors(jq, options.index);
        for (var i = 0; i < editors.length; i++) {
            if (editors[i].field == options.field) {
                return editors[i];
            }
        }
        return null;
    };
    //创建编辑器
    function createEditor(jq, index) {
        var opts = $.data(jq, "datagrid").options;
        var tr = opts.finder.getTr(jq, index);
        tr.children("td").each(function () {
            var cell = $(this).find("div.datagrid-cell");
            var field = $(this).attr("field");
            var col = _getColumnOption(jq, field);
            if (col && col.editor) {
                var type, editorOpts;
                if (typeof col.editor == "string") {
                    type = col.editor;
                } else {
                    type = col.editor.type;
                    editorOpts = col.editor.options;
                }
                var editor = opts.editors[type];
                if (editor) {
                    var html = cell.html();
                    var width = cell._outerWidth();
                    cell.addClass("datagrid-editable");
                    cell._outerWidth(width);
                    cell.html("<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\"><tr><td></td></tr></table>");
                    cell.children("table").bind("click dblclick contextmenu", function (e) {
                        e.stopPropagation();
                    });
                    $.data(cell[0], "datagrid.editor", { actions: editor, target: editor.init(cell.find("td"), editorOpts), field: field, type: type, oldHtml: html });
                }
            }
        });
        _fixRowHeight(jq, index, true);
    };
    //销毁编辑器
    function destroyEditor(jq, index) {
        var opts = $.data(jq, "datagrid").options;
        var tr = opts.finder.getTr(jq, index);
        tr.children("td").each(function () {
            var cell = $(this).find("div.datagrid-editable");
            if (cell.length) {
                var ed = $.data(cell[0], "datagrid.editor");
                if (ed.actions.destroy) {
                    ed.actions.destroy(ed.target);
                }
                cell.html(ed.oldHtml);
                $.removeData(cell[0], "datagrid.editor");
                cell.removeClass("datagrid-editable");
                cell.css("width", "");
            }
        });
    };
    //验证指定的行,当验证有效的时候返回true
    function validateRow(jq, index) {
        var tr = $.data(jq, "datagrid").options.finder.getTr(jq, index);
        if (!tr.hasClass("datagrid-row-editing")) {
            return true;
        }
        var vbox = tr.find(".validatebox-text");
        vbox.validatebox("validate");
        vbox.trigger("mouseleave");
        var invalid = tr.find(".validatebox-invalid");
        return invalid.length == 0;
    };
    //从上一次的提交获取改变的所有行。类型参数指明用哪些类型改变的行,可以使用的值有:inserted,deleted,updated等。当类型参数未配置的时候返回所有改变的行
    function _getChanges(jq, type) {
        var insertedRows = $.data(jq, "datagrid").insertedRows;
        var deletedRows = $.data(jq, "datagrid").deletedRows;
        var updatedRows = $.data(jq, "datagrid").updatedRows;
        if (!type) {
            var rows = [];
            rows = rows.concat(insertedRows);
            rows = rows.concat(deletedRows);
            rows = rows.concat(updatedRows);
            return rows;
        } else {
            if (type == "inserted") {
                return insertedRows;
            } else {
                if (type == "deleted") {
                    return deletedRows;
                } else {
                    if (type == "updated") {
                        return updatedRows;
                    }
                }
            }
        }
        return [];
    };
    //删除行
    function _deleteRow(jq, index) {
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        var data = datagrid.data;
        var insertedRows = datagrid.insertedRows;
        var deletedRows = datagrid.deletedRows;
        $(jq).datagrid("cancelEdit", index);
        var row = data.rows[index];
        if (getObjectIndex(insertedRows, row) >= 0) {
            unSelectedRowsById(insertedRows, row);
        } else {
            deletedRows.push(row);
        }
        unSelectedRowsById(datagrid.selectedRows, opts.idField, data.rows[index][opts.idField]);
        unSelectedRowsById(datagrid.checkedRows, opts.idField, data.rows[index][opts.idField]);
        opts.view.deleteRow.call(opts.view, jq, index);
        if (opts.height == "auto") {
            _fixRowHeight(jq);
        }
        $(jq).datagrid("getPager").pagination("refresh", { total: data.total });
    };
    //插入一个新行,参数包括一下属性:
    //index:要插入的行索引,如果该索引值未定义,则追加新行。
    //row:行数据
    function _insertRow(jq, param) {
        var data = $.data(jq, "datagrid").data;
        var view = $.data(jq, "datagrid").options.view;
        var insertedRows = $.data(jq, "datagrid").insertedRows;
        view.insertRow.call(view, jq, param.index, param.row);
        insertedRows.push(param.row);
        $(jq).datagrid("getPager").pagination("refresh", { total: data.total });
    };
    //追加一个新行。新行将被添加到最后的位置
    function _appendRow(jq, row) {
        var data = $.data(jq, "datagrid").data;
        var view = $.data(jq, "datagrid").options.view;
        var insertedRows = $.data(jq, "datagrid").insertedRows;
        view.insertRow.call(view, jq, null, row);
        insertedRows.push(row);
        $(jq).datagrid("getPager").pagination("refresh", { total: data.total });
    };
    //加载本地数据,旧的行将被移除
    function _loadData(jq) {
        var datagrid = $.data(jq, "datagrid");
        var data = datagrid.data;
        var rows = data.rows;
        var originalRows = [];
        for (var i = 0; i < rows.length; i++) {
            originalRows.push($.extend({}, rows[i]));
        }
        datagrid.originalRows = originalRows;
        datagrid.updatedRows = [];
        datagrid.insertedRows = [];
        datagrid.deletedRows = [];
    };
    //提交所有从加载或者上一次调用acceptChanges函数后更改的数据
    function _acceptChanges(jq) {
        var data = $.data(jq, "datagrid").data;
        var ok = true;
        for (var i = 0, len = data.rows.length; i < len; i++) {
            if (validateRow(jq, i)) {
                _endEdit(jq, i, false);
            } else {
                ok = false;
            }
        }
        if (ok) {
            _loadData(jq);
        }
    };
    //回滚所有从创建或者上一次调用acceptChanges函数后更改的数据
    function _rejectChanges(jq) {
        var datagrid = $.data(jq, "datagrid");
        var opts = datagrid.options;
        var originalRows = datagrid.originalRows;
        var insertedRows = datagrid.insertedRows;
        var deletedRows = datagrid.deletedRows;
        var selectedRows = datagrid.selectedRows;
        var checkedRows = datagrid.checkedRows;
        var data = datagrid.data;
        function Rowids(a) {
            var ids = [];
            for (var i = 0; i < a.length; i++) {
                ids.push(a[i][opts.idField]);
            }
            return ids;
        };
        function selectRecord(ids, type) {
            for (var i = 0; i < ids.length; i++) {
                var index = _getRowIndex(jq, ids[i]);
                (type == "s" ? _selectRow : _checkRow)(jq, index, true);
            }
        };
        for (var i = 0; i < data.rows.length; i++) {
            _endEdit(jq, i, true);
        }
        var sids = Rowids(selectedRows);
        var cids = Rowids(checkedRows);
        selectedRows.splice(0, selectedRows.length);
        checkedRows.splice(0, checkedRows.length);
        data.total += deletedRows.length - insertedRows.length;
        data.rows = originalRows;
        _removeData(jq, data);
        selectRecord(sids, "s");
        selectRecord(cids, "c");
        _loadData(jq);
    };
    //加载和显示第一页的所有行。如果指定了'param',它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据
    function _load(jq, param) {
        var opts = $.data(jq, "datagrid").options;
        if (param) {
            opts.queryParams = param;
        }
        var param = $.extend({}, opts.queryParams);
        if (opts.pagination) {
            $.extend(param, { page: opts.pageNumber, rows: opts.pageSize });
        }
        if (opts.sortName) {
            $.extend(param, { sort: opts.sortName, order: opts.sortOrder });
        }
        if (opts.onBeforeLoad.call(jq, param) == false) {
            return;
        }
        $(jq).datagrid("loading");
        setTimeout(function () {
            doRequest();
        }, 0);
        function doRequest() {
            var loaded = opts.loader.call(jq, param, function (data) {
                setTimeout(function () {
                    $(jq).datagrid("loaded");
                }, 0);
                _removeData(jq, data);
                setTimeout(function () {
                    _loadData(jq);
                }, 0);
            }, function () {
                setTimeout(function () {
                    $(jq).datagrid("loaded");
                }, 0);
                opts.onLoadError.apply(jq, arguments);
            });
            if (loaded == false) {
                $(jq).datagrid("loaded");
            }
        };
    };
    //合并单元格,options包含以下属性:
    //index:行索引。
    //field:字段名称。
    //rowspan:合并的行数。
    //colspan:合并的列数。
    function _mergeCells(jq, options) {
        var opts = $.data(jq, "datagrid").options;
        options.rowspan = options.rowspan || 1;
        options.colspan = options.colspan || 1;
        if (options.rowspan == 1 && options.colspan == 1) {
            return;
        }
        var tr = opts.finder.getTr(jq, (options.index != undefined ? options.index : options.id));
        if (!tr.length) {
            return;
        }
        var row = opts.finder.getRow(jq, tr);
        var field = row[options.field];
        var td = tr.find("td[field=\"" + options.field + "\"]");
        td.attr("rowspan", options.rowspan).attr("colspan", options.colspan);
        td.addClass("datagrid-td-merged");
        for (var i = 1; i < options.colspan; i++) {
            td = td.next();
            td.hide();
            row[td.attr("field")] = field;
        }
        for (var i = 1; i < options.rowspan; i++) {
            tr = tr.next();
            if (!tr.length) {
                break;
            }
            var row = opts.finder.getRow(jq, tr);
            var td = tr.find("td[field=\"" + options.field + "\"]").hide();
            row[td.attr("field")] = field;
            for (var j = 1; j < options.colspan; j++) {
                td = td.next();
                td.hide();
                row[td.attr("field")] = field;
            }
        }
        _91(jq);
    };
    //实例化
    $.fn.datagrid = function (options, param) {
        if (typeof options == "string") {
            return $.fn.datagrid.methods[options](this, param);
        }
        options = options || {};
        return this.each(function () {
            var state = $.data(this, "datagrid");
            var opts;
            if (state) {
                opts = $.extend(state.options, options);
                state.options = opts;
            } else {
                opts = $.extend({}, $.extend({}, $.fn.datagrid.defaults, { queryParams: {} }),
                    $.fn.datagrid.parseOptions(this),
                    options);
                $(this).css("width", "").css("height", "");
                var gridWrap = wrapGrid(this, opts.rownumbers);
                if (!opts.columns) {
                    opts.columns = gridWrap.columns;
                }
                if (!opts.frozenColumns) {
                    opts.frozenColumns = gridWrap.frozenColumns;
                }
                opts.columns = $.extend(true, [], opts.columns);
                opts.frozenColumns = $.extend(true, [], opts.frozenColumns);
                opts.view = $.extend({}, opts.view);
                $.data(this, "datagrid", {
                    options: opts,
                    panel: gridWrap.panel,
                    dc: gridWrap.dc,
                    selectedRows: [],
                    checkedRows: [],
                    data: { total: 0, rows: [] },
                    originalRows: [],
                    updatedRows: [],
                    insertedRows: [],
                    deletedRows: []
                });
            }
            init(this);
            if (opts.data) {
                _removeData(this, opts.data);
                _loadData(this);
            } else {
                var data = getGridData(this);
                if (data.total > 0) {
                    _removeData(this, data);
                    _loadData(this);
                }
            }
            _resize(this);
            _load(this);
            bingEvent(this);
        });
    };
    //editors 重写默认值对象
    var editors = {
        //文本框
        text: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<input type=\"text\" class=\"datagrid-editable-input\">").appendTo(container);
                return editor;
            },
            //从编辑器中获取值
            getValue: function () {
                return $(target).val();
            },
            //向编辑器中写入值
            setValue: function (target, value) {
                $(target).val(value);
            },
            //向编辑器中写入值
            resize: function (target, width) {
                $(target)._outerWidth(width);
            }
        },
        //多行文本
        textarea: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<textarea class=\"datagrid-editable-input\"></textarea>").appendTo(container);
                return editor;
            },
            getValue: function (target) {
                return $(target).val();
            },
            setValue: function (target, value) {
                $(target).val(value);
            },
            resize: function (target, width) {
                $(target)._outerWidth(width);
            }
        },
        //选择框
        checkbox: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<input type=\"checkbox\">").appendTo(container);
                editor.val(options.on);
                editor.attr("offval", options.off);
                return editor;
            },
            getValue: function (target) {
                if ($(target).is(":checked")) {
                    return $(target).val();
                } else {
                    return $(target).attr("offval");
                }
            },
            setValue: function (target, value) {
                var checked = false;
                if ($(target).val() == value) {
                    checked = true;
                }
                $(target)._propAttr("checked", checked);
            }
        },
        //数值输入框
        numberbox: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<input type=\"text\" class=\"datagrid-editable-input\">").appendTo(container);
                editor.numberbox(options);
                return editor;
            },
            destroy: function (target) {
                $(target).numberbox("destroy");
            },
            getValue: function (target) {
                $(target).blur();
                return $(target).numberbox("getValue");
            },
            setValue: function (target, value) {
                $(target).numberbox("setValue", value);
            },
            resize: function (target, width) {
                $(target)._outerWidth(width);
            }
        },
        //验证框
        validatebox: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<input type=\"text\" class=\"datagrid-editable-input\">").appendTo(container);
                editor.validatebox(options);
                return editor;
            },
            destroy: function (target) {
                $(target).validatebox("destroy");
            },
            getValue: function (target) {
                return $(target).val();
            },
            setValue: function (target, value) {
                $(target).val(value);
            },
            resize: function (target, width) {
                $(target)._outerWidth(width);
            }
        },
        //日期框
        datebox: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<input type=\"text\">").appendTo(container);
                editor.datebox(options);
                return editor;
            },
            destroy: function (target) {
                $(target).datebox("destroy");
            },
            getValue: function (target) {
                return $(target).datebox("getValue");
            },
            setValue: function (target, value) {
                $(target).datebox("setValue", value);
            },
            resize: function (target, width) {
                $(target).datebox("resize", width);
            }
        },
        //下拉框
        combobox: {
            //初始化编辑器并返回目标对象
            init: function (container, options) {
                var editor = $("<input type=\"text\">").appendTo(container);
                editor.combobox(options || {});
                return editor;
            },
            destroy: function (target) {
                $(target).combobox("destroy");
            },
            getValue: function (target) {
                return $(target).combobox("getValue");
            },
            setValue: function (target, value) {
                $(target).combobox("setValue", value);
            },
            resize: function (target, width) {
                $(target).combobox("resize", width);
            }
        },
        //下拉树
        combotree: {
            //初始化编辑器并返回目标对象
            init: function (container, target) {
                var editor = $("<input type=\"text\">").appendTo(container);
                editor.combotree(target);
                return editor;
            },
            destroy: function (target) {
                $(target).combotree("destroy");
            },
            getValue: function (target) {
                return $(target).combotree("getValue");
            },
            setValue: function (target, value) {
                $(target).combotree("setValue", value);
            },
            resize: function (target, width) {
                $(target).combotree("resize", width);
            }
        }
    };

    //表格默认方法
    $.fn.datagrid.methods = {
        //返回属性对象
        options: function (jq) {
            var opts = $.data(jq[0], "datagrid").options;
            var panelOpts = $.data(jq[0], "datagrid").panel.panel("options");
            var opts = $.extend(opts,
                {
                    width: panelOpts.width,
                    height: panelOpts.height,
                    closed: panelOpts.closed,
                    collapsed: panelOpts.collapsed,
                    minimized: panelOpts.minimized,
                    maximized: panelOpts.maximized
                });
            return opts;
        },
        //返回面板对象
        getPanel: function (jq) {
            return $.data(jq[0], "datagrid").panel;
        },
        //返回页面对象
        getPager: function (jq) {
            return $.data(jq[0], "datagrid").panel.children("div.datagrid-pager");
        },
        //返回列字段。如果设置了frozen属性为true,将返回固定列的字段名
        getColumnFields: function (jq, frozen) {
            return _getColumnFields(jq[0], frozen);
        },
        //返回指定列属性
        getColumnOption: function (jq, field) {
            return _getColumnOption(jq[0], field);
        },
        //做调整和布局
        resize: function (jq, param) {
            return jq.each(function () {
                _resize(this, param);
            });
        },
        //加载和显示第一页的所有行。如果指定了'param',它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据
        load: function (jq, param) {
            return jq.each(function () {
                var opts = $(this).datagrid("options");
                opts.pageNumber = 1;
                var Pager = $(this).datagrid("getPager");
                Pager.pagination({ pageNumber: 1 });
                _load(this, param);
            });
        },
        //重载行。等同于'load'方法,但是它将保持在当前页
        reload: function (jq, param) {
            return jq.each(function () {
                _load(this, param);
            });
        },
        //重载页脚行。代码示例
        reloadFooter: function (jq, footer) {
            return jq.each(function () {
                var opts = $.data(this, "datagrid").options;
                var dc = $.data(this, "datagrid").dc;
                if (footer) {
                    $.data(this, "datagrid").footer = footer;
                }
                if (opts.showFooter) {
                    opts.view.renderFooter.call(opts.view, this, dc.footer2, false);
                    opts.view.renderFooter.call(opts.view, this, dc.footer1, true);
                    if (opts.view.onAfterRender) {
                        opts.view.onAfterRender.call(opts.view, this);
                    }
                    $(this).datagrid("fixRowHeight");
                }
            });
        },
        //显示载入状态
        loading: function (jq) {
            return jq.each(function () {
                var opts = $.data(this, "datagrid").options;
                $(this).datagrid("getPager").pagination("loading");
                if (opts.loadMsg) {
                    var Panel = $(this).datagrid("getPanel");
                    $("<div class=\"datagrid-mask\" style=\"display:block\"></div>").appendTo(Panel);
                    var msg = $("<div class=\"datagrid-mask-msg\" style=\"display:block;left:50%\"></div>").html(opts.loadMsg).appendTo(Panel);
                    msg.css("marginLeft", -msg.outerWidth() / 2);
                }
            });
        },
        //隐藏载入状态
        loaded: function (jq) {
            return jq.each(function () {
                $(this).datagrid("getPager").pagination("loaded");
                var Panel = $(this).datagrid("getPanel");
                Panel.children("div.datagrid-mask-msg").remove();
                Panel.children("div.datagrid-mask").remove();
            });
        },
        //使列自动展开/收缩到合适的数据表格宽度
        fitColumns: function (jq) {
            return jq.each(function () {
                _fitColumns(this);
            });
        },
        //固定列大小。如果'field'参数未配置,所有列大小将都是固定的
        fixColumnSize: function (jq, field) {
            return jq.each(function () {
                _fixColumnSize(this, field);
            });
        },
        //固定指定列高度。如果'index'参数未配置,所有行高度都是固定的
        fixRowHeight: function (jq, index) {
            return jq.each(function () {
                _fixRowHeight(this, index);
            });
        },
        //冻结指定行,当数据表格表格向下滚动的时候始终保持被冻结的行显示在顶部
        freezeRow: function (jq, index) {
            return jq.each(function () {
                _freezeRow(this, index);
            });
        },
        //自动调整列宽度以适应内容
        autoSizeColumn: function (jq, field) {
            return jq.each(function () {
                _autoSizeColumn(this, field);
            });
        },
        //加载本地数据,旧的行将被移除
        loadData: function (jq, data) {
            return jq.each(function () {
                _removeData(this, data);
                _loadData(this);
            });
        },
        //返回加载完毕后的数据
        getData: function (jq) {
            return $.data(jq[0], "datagrid").data;
        },
        //返回当前页的所有行
        getRows: function (jq) {
            return $.data(jq[0], "datagrid").data.rows;
        },
        //返回页脚行
        getFooterRows: function (jq) {
            return $.data(jq[0], "datagrid").footer;
        },
        //返回指定行的索引号,该行的参数可以是一行记录或一个ID字段值
        getRowIndex: function (jq, id) {
            return _getRowIndex(jq[0], id);
        },
        //在复选框呗选中的时候返回所有行
        getChecked: function (jq) {
            return _getChecked(jq[0]);
        },
        //返回第一个被选中的行或如果没有选中的行则返回null
        getSelected: function (jq) {
            var rows = _getSelected(jq[0]);
            return rows.length > 0 ? rows[0] : null;
        },
        //返回所有被选中的行,当没有记录被选中的时候将返回一个空数组
        getSelections: function (jq) {
            return _getSelected(jq[0]);
        },
        //清除所有选择的行
        clearSelections: function (jq) {
            return jq.each(function () {
                var selectedRows = $.data(this, "datagrid").selectedRows;
                selectedRows.splice(0, selectedRows.length);
                _clearSelections(this);
            });
        },
        //清楚所有勾选的行
        clearChecked: function (jq) {
            return jq.each(function () {
                var checkedRows = $.data(this, "datagrid").checkedRows;
                checkedRows.splice(0, checkedRows.length);
                _clearChecked(this);
            });
        },
        //clearChecked
        selectAll: function (jq) {
            return jq.each(function () {
                _selectAll(this);
            });
        },
        //取消选择所有当前页中所有的行
        unselectAll: function (jq) {
            return jq.each(function () {
                _clearSelections(this);
            });
        },
        //选择一行,行索引从0开始
        selectRow: function (jq, index) {
            return jq.each(function () {
                _selectRow(this, index);
            });
        },
        //通过ID值参数选择一行
        selectRecord: function (jq, id) {
            return jq.each(function () {
                _selectRecord(this, id);
            });
        },
        //取消选择一行
        unselectRow: function (jq, index) {
            return jq.each(function () {
                _unselectRow(this, index);
            });
        },
        //勾选一行,行索引从0开始
        checkRow: function (jq, index) {
            return jq.each(function () {
                _checkRow(this, index);
            });
        },

        uncheckRow: function (jq, _1b7) {
            return jq.each(function () {
                _uncheckRow(this, _1b7);
            });
        },
        //勾选当前页中的所有行
        checkAll: function (jq) {
            return jq.each(function () {
                _checkAll(this);
            });
        },
        //取消勾选当前页中的所有行
        uncheckAll: function (jq) {
            return jq.each(function () {
                _clearChecked(this);
            });
        },
        //开始编辑行
        beginEdit: function (jq, index) {
            return jq.each(function () {
                _beginEdit(this, index);
            });
        },
        //结束编辑行
        endEdit: function (jq, index) {
            return jq.each(function () {
                _endEdit(this, index, false);
            });
        },
        //取消编辑行
        cancelEdit: function (jq, index) {
            return jq.each(function () {
                _endEdit(this, index, true);
            });
        },
        //获取指定行的编辑器。每个编辑器都有以下属性:
        //actions:编辑器可以执行的动作,同编辑器定义。
        //target:目标编辑器的jQuery对象。
        //field:字段名称。
        //type:编辑器类型,比如:'text','combobox','datebox'等。
        getEditors: function (jq, index) {
            return _getEditors(jq[0], index);
        },
        //获取指定编辑器,options包含2个属性:
        //index:行索引。
        //field:字段名称。 
        getEditor: function (jq, options) {
            return _getEditor(jq[0], options);
        },
        //刷新行。
        refreshRow: function (jq, index) {
            return jq.each(function () {
                var opts = $.data(this, "datagrid").options;
                opts.view.refreshRow.call(opts.view, this, index);
            });
        },
        //验证指定的行,当验证有效的时候返回true
        validateRow: function (jq, index) {
            return validateRow(jq[0], index);
        },
        //更新指定行,参数包含下列属性:
        //index:执行更新操作的行索引。
        //row:更新行的新数据
        updateRow: function (jq, param) {
            return jq.each(function () {
                var opts = $.data(this, "datagrid").options;
                opts.view.updateRow.call(opts.view, this, param.index, param.row);
            });
        },
        //追加一个新行。新行将被添加到最后的位置
        appendRow: function (jq, row) {
            return jq.each(function () {
                _appendRow(this, row);
            });
        },
        //插入一个新行,参数包括一下属性:
        //index:要插入的行索引,如果该索引值未定义,则追加新行。
        //row:行数据
        insertRow: function (jq, param) {
            return jq.each(function () {
                _insertRow(this, param);
            });
        },
        //删除行
        deleteRow: function (jq, index) {
            return jq.each(function () {
                _deleteRow(this, index);
            });
        },
        //从上一次的提交获取改变的所有行。类型参数指明用哪些类型改变的行,可以使用的值有:inserted,deleted,updated等。当类型参数未配置的时候返回所有改变的行
        getChanges: function (jq, type) {
            return _getChanges(jq[0], type);
        },
        //提交所有从加载或者上一次调用acceptChanges函数后更改的数据
        acceptChanges: function (jq) {
            return jq.each(function () {
                _acceptChanges(this);
            });
        },
        //回滚所有从创建或者上一次调用acceptChanges函数后更改的数据
        rejectChanges: function (jq) {
            return jq.each(function () {
                _rejectChanges(this);
            });
        },
        //合并单元格,options包含以下属性:
        //index:行索引。
        //field:字段名称。
        //rowspan:合并的行数。
        //colspan:合并的列数。
        mergeCells: function (jq, options) {
            return jq.each(function () {
                _mergeCells(this, options);
            });
        },
        //显示指定的列
        showColumn: function (jq, field) {
            return jq.each(function () {
                var Panel = $(this).datagrid("getPanel");
                Panel.find("td[field=\"" + field + "\"]").show();
                $(this).datagrid("getColumnOption", field).hidden = false;
                $(this).datagrid("fitColumns");
            });
        },
        //隐藏指定的列
        hideColumn: function (jq, field) {
            return jq.each(function () {
                var Panel = $(this).datagrid("getPanel");
                Panel.find("td[field=\"" + field + "\"]").hide();
                $(this).datagrid("getColumnOption", field).hidden = true;
                $(this).datagrid("fitColumns");
            });
        }
    };

    $.fn.datagrid.parseOptions = function (_1c8) {
        var t = $(_1c8);
        return $.extend({},
            $.fn.panel.parseOptions(_1c8),
            $.parser.parseOptions(_1c8, ["url", "toolbar", "idField", "sortName", "sortOrder", "pagePosition", "resizeHandle",
                { fitColumns: "boolean", autoRowHeight: "boolean", striped: "boolean", nowrap: "boolean" },
                { rownumbers: "boolean", singleSelect: "boolean", checkOnSelect: "boolean", selectOnCheck: "boolean" },
                { pagination: "boolean", pageSize: "number", pageNumber: "number" },
                { remoteSort: "boolean", showHeader: "boolean", showFooter: "boolean" },
                { scrollbarSize: "number" }]), {
                    pageList: (t.attr("pageList") ? eval(t.attr("pageList")) : undefined),
                    loadMsg: (t.attr("loadMsg") != undefined ? t.attr("loadMsg") : undefined),
                    rowStyler: (t.attr("rowStyler") ? eval(t.attr("rowStyler")) : undefined)
                });
    };
    //定义数据表格的视图 该视图是一个对象,将告诉数据表格如何渲染行。该对象必须定义下列函
    var view = {
        //    数据加载时调用。
        //target:DOM对象,数据表格对象。
        //container:行容器。
        //frozen:指明如何渲染冻结容器。
        render: function (target, container, frozen) {
            var datagrid = $.data(target, "datagrid");
            var opts = datagrid.options;
            var rows = datagrid.data.rows;
            var fields = $(target).datagrid("getColumnFields", frozen);
            if (frozen) {
                if (!(opts.rownumbers || (opts.frozenColumns && opts.frozenColumns.length))) {
                    return;
                }
            }
            var html = ["<table class=\"datagrid-btable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>"];
            for (var i = 0; i < rows.length; i++) {
                var cls = (i % 2 && opts.striped) ? "class=\"datagrid-row datagrid-row-alt\"" : "class=\"datagrid-row\"";
                var style = opts.rowStyler ? opts.rowStyler.call(target, i, rows[i]) : "";
                var style = style ? "style=\"" + style + "\"" : "";
                var _1d2 = datagrid.rowIdPrefix + "-" + (frozen ? 1 : 2) + "-" + i;
                html.push("<tr id=\"" + _1d2 + "\" datagrid-row-index=\"" + i + "\" " + cls + " " + style + ">");
                html.push(this.renderRow.call(this, target, fields, frozen, i, rows[i]));
                html.push("</tr>");
            }
            html.push("</tbody></table>");
            $(container).html(html.join(""));
        },
        //这是一个选择函数来渲染行页脚
        renderFooter: function (target, container, frozen) {
            var opts = $.data(target, "datagrid").options;
            var rows = $.data(target, "datagrid").footer || [];
            var fields = $(target).datagrid("getColumnFields", frozen);
            var html = ["<table class=\"datagrid-ftable\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>"];
            for (var i = 0; i < rows.length; i++) {
                html.push("<tr class=\"datagrid-row\" datagrid-row-index=\"" + i + "\">");
                html.push(this.renderRow.call(this, target, fields, frozen, i, rows[i]));
                html.push("</tr>");
            }
            html.push("</tbody></table>");
            $(container).html(html.join(""));
        },
        //这是一个属性功能,将调用render函数
        renderRow: function (target, fields, frozen, rowIndex, rowData) {
            var opts = $.data(target, "datagrid").options;
            var cc = [];
            if (frozen && opts.rownumbers) {
                var rowIndex = rowIndex + 1;
                if (opts.pagination) {
                    rowIndex += (opts.pageNumber - 1) * opts.pageSize;
                }
                cc.push("<td class=\"datagrid-td-rownumber\"><div class=\"datagrid-cell-rownumber\">" + rowIndex + "</div></td>");
            }
            for (var i = 0; i < fields.length; i++) {
                var field = fields[i];
                var col = $(target).datagrid("getColumnOption", field);
                if (col) {
                    var _1df = rowData[field];
                    var style = col.styler ? (col.styler(_1df, rowData, rowIndex) || "") : "";
                    var style = col.hidden ? "style=\"display:none;" + style + "\"" : (style ? "style=\"" + style + "\"" : "");
                    cc.push("<td field=\"" + field + "\" " + style + ">");
                    if (col.checkbox) {
                        var style = "";
                    } else {
                        var style = "";
                        if (col.align) {
                            style += "text-align:" + col.align + ";";
                        }
                        if (!opts.nowrap) {
                            style += "white-space:normal;height:auto;";
                        } else {
                            if (opts.autoRowHeight) {
                                style += "height:auto;";
                            }
                        }
                    }
                    cc.push("<div style=\"" + style + "\" ");
                    if (col.checkbox) {
                        cc.push("class=\"datagrid-cell-check ");
                    } else {
                        cc.push("class=\"datagrid-cell " + col.cellClass);
                    }
                    cc.push("\">");
                    if (col.checkbox) {
                        cc.push("<input type=\"checkbox\" name=\"" + field + "\" value=\"" + (_1df != undefined ? _1df : "") + "\"/>");
                    } else {
                        if (col.formatter) {
                            cc.push(col.formatter(_1df, rowData, rowIndex));
                        } else {
                            cc.push(_1df);
                        }
                    }
                    cc.push("</div>");
                    cc.push("</td>");
                }
            }
            return cc.join("");
        },
        //定义如何刷新指定的行
        refreshRow: function (target, rowIndex) {
            this.updateRow.call(this, target, rowIndex, {});
        },
        //更新行
        updateRow: function (target, rowIndex, row) {
            var opts = $.data(target, "datagrid").options;
            var rows = $(target).datagrid("getRows");
            $.extend(rows[rowIndex], row);
            var style = opts.rowStyler ? opts.rowStyler.call(target, rowIndex, rows[rowIndex]) : "";
            function _1e7(_1e8) {
                var _1e9 = $(target).datagrid("getColumnFields", _1e8);
                var tr = opts.finder.getTr(target, rowIndex, "body", (_1e8 ? 1 : 2));
                var _1ea = tr.find("div.datagrid-cell-check input[type=checkbox]").is(":checked");
                tr.html(this.renderRow.call(this, target, _1e9, _1e8, rowIndex, rows[rowIndex]));
                tr.attr("style", style || "");
                if (_1ea) {
                    tr.find("div.datagrid-cell-check input[type=checkbox]")._propAttr("checked", true);
                }
            };
            _1e7.call(this, true);
            _1e7.call(this, false);
            $(target).datagrid("fixRowHeight", rowIndex);
        },
        //插入行
        insertRow: function (target, rowIndex, row) {
            var datagrid = $.data(target, "datagrid");
            var opts = datagrid.options;
            var dc = datagrid.dc;
            var data = datagrid.data;
            if (rowIndex == undefined || rowIndex == null) {
                rowIndex = data.rows.length;
            }
            if (rowIndex > data.rows.length) {
                rowIndex = data.rows.length;
            }
            function _1ee(_1ef) {
                var _1f0 = _1ef ? 1 : 2;
                for (var i = data.rows.length - 1; i >= rowIndex; i--) {
                    var tr = opts.finder.getTr(target, i, "body", _1f0);
                    tr.attr("datagrid-row-index", i + 1);
                    tr.attr("id", datagrid.rowIdPrefix + "-" + _1f0 + "-" + (i + 1));
                    if (_1ef && opts.rownumbers) {
                        var _1f1 = i + 2;
                        if (opts.pagination) {
                            _1f1 += (opts.pageNumber - 1) * opts.pageSize;
                        }
                        tr.find("div.datagrid-cell-rownumber").html(_1f1);
                    }
                }
            };
            function _1f2(_1f3) {
                var _1f4 = _1f3 ? 1 : 2;
                var _1f5 = $(target).datagrid("getColumnFields", _1f3);
                var _1f6 = datagrid.rowIdPrefix + "-" + _1f4 + "-" + rowIndex;
                var tr = "<tr id=\"" + _1f6 + "\" class=\"datagrid-row\" datagrid-row-index=\"" + rowIndex + "\"></tr>";
                if (rowIndex >= data.rows.length) {
                    if (data.rows.length) {
                        opts.finder.getTr(target, "", "last", _1f4).after(tr);
                    } else {
                        var cc = _1f3 ? dc.body1 : dc.body2;
                        cc.html("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tbody>" + tr + "</tbody></table>");
                    }
                } else {
                    opts.finder.getTr(target, rowIndex + 1, "body", _1f4).before(tr);
                }
            };
            _1ee.call(this, true);
            _1ee.call(this, false);
            _1f2.call(this, true);
            _1f2.call(this, false);
            data.total += 1;
            data.rows.splice(rowIndex, 0, row);
            this.refreshRow.call(this, target, rowIndex);
        },
        //删除行
        deleteRow: function (target, rowIndex) {
            var datagrid = $.data(target, "datagrid");
            var opts = datagrid.options;
            var data = datagrid.data;
            function _1fa(_1fb) {
                var _1fc = _1fb ? 1 : 2;
                for (var i = rowIndex + 1; i < data.rows.length; i++) {
                    var tr = opts.finder.getTr(target, i, "body", _1fc);
                    tr.attr("datagrid-row-index", i - 1);
                    tr.attr("id", datagrid.rowIdPrefix + "-" + _1fc + "-" + (i - 1));
                    if (_1fb && opts.rownumbers) {
                        var _1fd = i;
                        if (opts.pagination) {
                            _1fd += (opts.pageNumber - 1) * opts.pageSize;
                        }
                        tr.find("div.datagrid-cell-rownumber").html(_1fd);
                    }
                }
            };
            opts.finder.getTr(target, rowIndex).remove();
            _1fa.call(this, true);
            _1fa.call(this, false);
            data.total -= 1;
            data.rows.splice(rowIndex, 1);
        },
        //在视图被呈现之前触发
        onBeforeRender: function (target, rows) {
        },
        //在视图呗呈现之后触发
        onAfterRender: function (target) {
            var opts = $.data(target, "datagrid").options;
            if (opts.showFooter) {
                var footer = $(target).datagrid("getPanel").find("div.datagrid-footer");
                footer.find("div.datagrid-cell-rownumber,div.datagrid-cell-check").css("visibility", "hidden");
            }
        }
    };
    //表格默认属性 以及事件(集成panel的属性和事件)
    $.fn.datagrid.defaults = $.extend({}, $.fn.panel.defaults, {
        frozenColumns: undefined,//同列属性,但是这些列将会被冻结在左侧
        columns: undefined,//数据表格列配置对象,详见列属性说明中更多的细节
        fitColumns: false,//真正的自动展开/收缩列的大小,以适应网格的宽度,防止水平滚动
        resizeHandle: "right",//调整列的位置,可用的值有:'left','right','both'。在使用'right'的时候用户可以通过拖动右侧边缘的列标题调整列
        autoRowHeight: true,//定义设置行的高度,根据该行的内容。设置为false可以提高负载性能
        toolbar: null,//顶部工具栏的数据表格面板。可能的值:1) 一个数组,每个工具属性都和linkbutton一样。 2) 选择器指定的工具栏
        striped: false,//是否显示斑马线效果
        method: "post",//该方法类型请求远程数据
        nowrap: true,//如果为true,则在同一行中显示数据。设置为true可以提高加载性能
        idField: null,//指明哪一个字段是标识字段
        url: null,//指明哪一个字段是标识字段
        data: null,//数据加载
        loadMsg: "Processing, please wait ...",//在从远程站点加载数据的时候显示提示消息
        rownumbers: false,//如果为true,则显示一个行号列
        singleSelect: false,//如果为true,则只允许选择一行
        selectOnCheck: true,//如果为true,单击复选框将永远选择行。        如果为false,选择行将不选中复选框
        checkOnSelect: true,//如果为true,当用户点击行的时候该复选框就会被选中或取消选中。   如果为false,当用户仅在点击该复选框的时候才会呗选中或取消
        pagination: false,//如果为true,则在数据表格控件底部显示分页工具栏
        pagePosition: "bottom",//定义分页工具栏的位置。可用的值有:'top','bottom','both'。
        pageNumber: 1,//在设置分页属性的时候初始化页码
        pageSize: 10,//在设置分页属性的时候初始化页面大小
        pageList: [10, 20, 30, 40, 50],//在设置分页属性的时候初始化页面大小
        queryParams: {},//在请求远程数据的时候发送额外的参数
        sortName: null,//定义哪些列可以进行排序
        sortOrder: "asc",//定义列的排序顺序,只能是'asc'或'desc'
        remoteSort: true,//定义从服务器对数据进行排序
        showHeader: true,//定义是否显示行头
        showFooter: false,//定义是否显示行脚
        scrollbarSize: 18,//滚动条的宽度(当滚动条是垂直的时候)或高度(当滚动条是水平的时候)。
        //返回样式如'background:red'。带2个参数的函数: rowIndex:该行索引从0开始  rowData:与此相对应的记录行
        rowStyler: function (rowIndex, rowData) {
        },
        //定义如何从远程服务器加载数据。返回false可以放弃本次请求动作。该函数接受以下参数:
        //param:参数对象传递给远程服务器。
        //success(data):当检索数据成功的时候会调用该回调函数。
        //error():当检索数据失败的时候会调用该回调函数
        loader: function (param, success, error) {
            var opts = $(this).datagrid("options");
            if (!opts.url) {
                return false;
            }
            $.ajax({
                type: opts.method, url: opts.url, data: param, dataType: "json", success: function (data) {
                    success(data);
                }, error: function () {
                    error.apply(this, arguments);
                }
            });
        },
        //返回过滤数据显示。该函数带一个参数'data'用来指向源数据(即:获取的数据源,比如Json对象)。您可以改变源数据的标准数据格式。这个函数必须返回包含'total'和'rows'属性的标准数据对象
        loadFilter: function (data) {
            if (typeof data.length == "number" && typeof data.splice == "function") {
                return { total: data.length, rows: data };
            } else {
                return data;
            }
        },
        //定义在编辑行的时候使用的编辑器
        editors: editors,

        finder: {
            getTr: function (target, rowIndex, type, step) {
                type = type || "body";
                step = step || 0;
                var _209 = $.data(target, "datagrid");
                var dc = _209.dc;
                var opts = _209.options;
                if (step == 0) {
                    var tr1 = opts.finder.getTr(target, rowIndex, type, 1);
                    var tr2 = opts.finder.getTr(target, rowIndex, type, 2);
                    return tr1.add(tr2);
                } else {
                    if (type == "body") {
                        var tr = $("#" + _209.rowIdPrefix + "-" + step + "-" + rowIndex);
                        if (!tr.length) {
                            tr = (step == 1 ? dc.body1 : dc.body2).find(">table>tbody>tr[datagrid-row-index=" + rowIndex + "]");
                        }
                        return tr;
                    } else {
                        if (type == "footer") {
                            return (step == 1 ? dc.footer1 : dc.footer2).find(">table>tbody>tr[datagrid-row-index=" + rowIndex + "]");
                        } else {
                            if (type == "selected") {
                                return (step == 1 ? dc.body1 : dc.body2).find(">table>tbody>tr.datagrid-row-selected");
                            } else {
                                if (type == "last") {
                                    return (step == 1 ? dc.body1 : dc.body2).find(">table>tbody>tr[datagrid-row-index]:last");
                                } else {
                                    if (type == "allbody") {
                                        return (step == 1 ? dc.body1 : dc.body2).find(">table>tbody>tr[datagrid-row-index]");
                                    } else {
                                        if (type == "allfooter") {
                                            return (step == 1 ? dc.footer1 : dc.footer2).find(">table>tbody>tr[datagrid-row-index]");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            getRow: function (_20a, p) {
                var _20b = (typeof p == "object") ? p.attr("datagrid-row-index") : p;
                return $.data(_20a, "datagrid").data.rows[parseInt(_20b)];
            }
        },
        //定义数据表格的视图
        view: view,
        //在载入请求数据数据之前触发,如果返回false可终止载入数据操作
        onBeforeLoad: function (param) {
        },
        //在数据加载成功的时候触发
        onLoadSuccess: function () {
        },
        //在数据加载成功的时候触发
        onLoadError: function () {
        },
        //在用户点击一行的时候触发,参数包括:
        //rowIndex:点击的行的索引值,该索引值从0开始。
        //rowData:对应于点击行的记录
        onClickRow: function (rowIndex, rowData) {
        },
        //在用户双击一行的时候触发,参数包括:
        //rowIndex:点击的行的索引值,该索引值从0开始。
        //rowData:对应于点击行的记录
        onDblClickRow: function (rowIndex, onDblClickRow) {
        },
        //在用户点击一个单元格的时候触发
        onClickCell: function (rowIndex, field, value) {
        },
        //在用户双击一个单元格的时候触发
        onDblClickCell: function (rowIndex, field, value) {
        },
        //在用户排序一列的时候触发,参数包括:
        //sort:排序列字段名称。
        //order:排序列的顺序(ASC或DESC)
        onSortColumn: function (sort, order) {
        },
        //在用户调整列大小的时候触发
        onResizeColumn: function (field, width) {
        },
        //在用户选择一行的时候触发,参数包括:
        //rowIndex:选择的行的索引值,索引从0开始。
        //rowData:对应于所选行的记录
        onSelect: function (rowIndex, rowData) {
        },
        //        在用户选择一行的时候触发,参数包括:
        //rowIndex:选择的行的索引值,索引从0开始。
        //rowData:对应于所选行的记录
        onUnselect: function (rowIndex, rowData) {
        },
        //在用户选择所有行的时候触发
        onSelectAll: function (rows) {
        },
        //在用户取消选择所有行的时候触发
        onUnselectAll: function (rows) {
        },
        //        在用户勾选一行的时候触发,参数包括:
        //rowIndex:选中的行索引,索引从0开始。
        //rowData:对应于所选行的记录
        onCheck: function (rowIndex, rowData) {
        },
        //        在用户取消勾选一行的时候触发,参数包括:
        //rowIndex:选中的行索引,索引从0开始。
        //rowData:对应于取消勾选行的记录
        onUncheck: function (rowIndex, rowData) {
        },
        //在用户勾选所有行的时候触发
        onCheckAll: function (rows) {
        },
        //在用户取消勾选所有行的时候触发
        onUncheckAll: function (rows) {
        },
        //        在用户开始编辑一行的时候触发,参数包括:
        //rowIndex:编辑行的索引,索引从0开始。
        //rowData:对应于编辑行的记录
        onBeforeEdit: function (rowIndex, rowData) {
        },
        //        在用户完成编辑一行的时候触发,参数包括:
        //rowIndex:编辑行的索引,索引从0开始。
        //rowData:对应于完成编辑的行的记录。
        //changes:更改后的字段(键)/值对
        onAfterEdit: function (rowIndex, rowData, changes) {
        },
        //        在用户取消编辑一行的时候触发,参数包括:
        //rowIndex:编辑行的索引,索引从0开始。
        //rowData:对应于编辑行的记录
        onCancelEdit: function (rowIndex, rowData) {
        },
        //在鼠标右击数据表格表格头的时候触发
        onHeaderContextMenu: function (e, field) {
        },
        //在鼠标右击一行记录的时候触发
        onRowContextMenu: function (e, rowIndex, rowData) {
        }
    });
})(jQuery);

实例代码:

这里只是对grid进行的单个插件引入的例子进行简单的说明
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Frozen Columns in DataGrid - jQuery EasyUI Demo</title>
    <link rel="stylesheet" type="text/css" href="../../themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="../../themes/icon.css">
    <link rel="stylesheet" type="text/css" href="../demo.css">
    
    <script type="text/javascript" src="../../jquery-1.8.0.min.js"></script>
    <script src="../../plugins2/jquery.parser.js"></script>
   
    <script src="../../plugins2/jquery.panel.js"></script>
     <script src="../../plugins/jquery.resizable.js"></script>
    <script src="../../plugins2/jquery.linkbutton.js"></script>
    <script src="../../plugins/jquery.pagination.js"></script>
    <script src="../../plugins2/jquery.datagrid.js"></script>
</head>
<body>
    <h2>Frozen Columns in DataGrid</h2>
    <div class="demo-info">
        <div class="demo-tip icon-tip"></div>
        <div>You can freeze some columns that can't scroll out of view.</div>
    </div>
    <div style="margin:10px 0;"></div>
    <table class="easyui-datagrid" title="Frozen Columns in DataGrid" style="width:700px;height:250px"
            data-options="rownumbers:true,singleSelect:true,url:'datagrid_data1.aspx'">
        <thead data-options="frozen:true">
            <tr>
                <th data-options="field:'itemid',width:100">Item ID</th>
                <th data-options="field:'productid',width:120">Product</th>
            </tr>
        </thead>
        <thead>
            <tr>
                <th data-options="field:'listprice',width:90,align:'right'">List Price</th>
                <th data-options="field:'unitcost',width:90,align:'right'">Unit Cost</th>
                <th data-options="field:'attr1',width:250">Attribute</th>
                <th data-options="field:'status',width:60,align:'center'">Status</th>
            </tr>
        </thead>
    </table>

</body>
</html>

[转载]Android--Matrix图片变换处理 - 承香墨影 - 博客园

mikel阅读(991)

[转载]Android–Matrix图片变换处理 – 承香墨影 – 博客园.

前言

本篇博客主要讲解一下如何处理对一个Bitmap对象进行处理,包括:缩放、旋转、位移、倾斜等。在最后将以一个简单的Demo来演示图片特效的变换。

本篇博客的主要内容:

  1. Matrix
  2. Matrix缩放
  3. Matrix旋转
  4. Matrix位移
  5. Matrix倾斜
  6. Matrix变换注意事项
  7. Matrix完整的Demo

 

Matrix

对于一个图片变换的处理,需要Matrix类的支持,它位于”Android.graphics.Matrix”包下,是Android提供的一个矩阵工具类,它本身不能对图像或View进行变换,但它可与其他API结合来控制图形、View的变换,如Canvas。

Matrix提供了一些方法来控制图片变换:

  • setTranslate(float dx,float dy):控制Matrix进行位移。
  • setSkew(float kx,float ky):控制Matrix进行倾斜,kx、ky为X、Y方向上的比例。
  • setSkew(float kx,float ky,float px,float py):控制Matrix以px、py为轴心进行倾斜,kx、ky为X、Y方向上的倾斜比例。
  • setRotate(float degrees):控制Matrix进行depress角度的旋转,轴心为(0,0)。
  • setRotate(float degrees,float px,float py):控制Matrix进行depress角度的旋转,轴心为(px,py)。
  • setScale(float sx,float sy):设置Matrix进行缩放,sx、sy为X、Y方向上的缩放比例。
  • setScale(float sx,float sy,float px,float py):设置Matrix以(px,py)为轴心进行缩放,sx、sy为X、Y方向上的缩放比例。

之前有提过,图片在内存中存放的就是一个一个的像素点,而对于图片的变换主要是处理图片的每个像素点,对每个像素点进行相应的变换,即可完成对图像的变换。上面已经列举了Matrix进行变换的常用方法,下面以几个Demo来讲解一下如何通过Matrix进行变换。

 

Matrix缩放

代码:

/**
* 缩放图片
*/
protected void bitmapScale(float x, float y) {
// 因为要将图片放大,所以要根据放大的尺寸重新创建Bitmap
Bitmap afterBitmap = Bitmap.createBitmap(
(int) (baseBitmap.getWidth() * x),
(int) (baseBitmap.getHeight() * y), baseBitmap.getConfig());
Canvas canvas = new Canvas(afterBitmap);
// 初始化Matrix对象
Matrix matrix = new Matrix();
// 根据传入的参数设置缩放比例
matrix.setScale(x, y);
// 根据缩放比例,把图片draw到Canvas上
canvas.drawBitmap(baseBitmap, matrix,paint);
iv_after.setImageBitmap(afterBitmap);
}

效果展示:

 

Matrix旋转

代码:

/**
* 图片移动
*/
protected void bitmapTranslate(float dx, float dy) {
// 需要根据移动的距离来创建图片的拷贝图大小
Bitmap afterBitmap = Bitmap.createBitmap(
(int) (baseBitmap.getWidth() * dx),
(int) (baseBitmap.getHeight() * dy), baseBitmap.getConfig());
Canvas canvas = new Canvas(afterBitmap);
Matrix matrix = new Matrix();
// 设置移动的距离
matrix.setTranslate(dx, dy);
canvas.drawBitmap(baseBitmap, matrix, paint);
iv_after.setImageBitmap(afterBitmap);
}

效果展示:

 

Matrix倾斜

代码:

/**
* 倾斜图片
*/
protected void bitmapSkew(float dx, float dy) {
// 根据图片的倾斜比例,计算变换后图片的大小,
Bitmap afterBitmap = Bitmap.createBitmap(baseBitmap.getWidth()
+ (int) (baseBitmap.getWidth() * dx), baseBitmap.getHeight()
+ (int) (baseBitmap.getHeight() * dy), baseBitmap.getConfig());
Canvas canvas = new Canvas(afterBitmap);
Matrix matrix = new Matrix();
// 设置图片倾斜的比例
matrix.setSkew(dx, dy);
canvas.drawBitmap(baseBitmap, matrix, paint);
iv_after.setImageBitmap(afterBitmap);
}

效果展示:

 

Matrix变换注意事项

上面几个小方法演示了如何使用Matrix进行变换,但是还有几点需要额外注意一下:

  • 对于一个从BitmapFactory.decodeXxx()方法加载的Bitmap对象而言,它是一个只读的,无法对其进行处理,必须使用Bitmap.createBitmap()方法重新创建一个Bitmap对象的拷贝,才可以对拷贝的Bitmap进行处理。
  • 因为图像的变换是针对每一个像素点的,所以有些变换可能发生像素点的丢失,这里需要使用Paint.setAnitiAlias(boolean)设置来消除锯齿,这样图片变换后的效果会好很多。
  • 在重新创建一个Bitmap对象的拷贝的时候,需要注意它的宽高,如果设置不妥,很可能变换后的像素点已经移动到”图片之外”去了。

 

Matrix完整的Demo

下面给出本篇博客讲解的使用Matrix的完整Demo代码。

布局代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_scale"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="缩放" />

        <Button
            android:id="@+id/btn_rotate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="旋转" />

        <Button
            android:id="@+id/btn_translate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="平移" />

        <Button
            android:id="@+id/btn_skew"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="倾斜" />
    </LinearLayout>
    <!-- 原始图片 -->
    <ImageView
        android:id="@+id/iv_base"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <!-- 处理之后的图片 -->
    <ImageView
        android:id="@+id/iv_after"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

activity_main.xml

 实现代码:

package cn.bgxt.canvasmatrixdemo;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;

public class MainActivity extends Activity {
    private Button btn_scale, btn_rotate, btn_translate, btn_skew;
    private ImageView iv_base, iv_after;
    private Bitmap baseBitmap;
    private Paint paint;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_scale = (Button) findViewById(R.id.btn_scale);
        btn_rotate = (Button) findViewById(R.id.btn_rotate);
        btn_translate = (Button) findViewById(R.id.btn_translate);
        btn_skew = (Button) findViewById(R.id.btn_skew);

        btn_scale.setOnClickListener(click);
        btn_rotate.setOnClickListener(click);
        btn_translate.setOnClickListener(click);
        btn_skew.setOnClickListener(click);

        iv_base = (ImageView) findViewById(R.id.iv_base);
        iv_after = (ImageView) findViewById(R.id.iv_after);

        baseBitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.ic_launcher);
        iv_base.setImageBitmap(baseBitmap);

        // 设置画笔,消除锯齿
        paint = new Paint();
        paint.setAntiAlias(true);
    }

    private View.OnClickListener click = new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            switch (v.getId()) {
            case R.id.btn_scale:
                bitmapScale(2.0f, 4.0f);
                break;
            case R.id.btn_rotate:
                bitmapRotate(180);
                break;
            case R.id.btn_translate:
                bitmapTranslate(20f, 20f);
                break;
            case R.id.btn_skew:
                bitmapSkew(0.2f, 0.4f);
                break;
            default:
                break;
            }

        }
    };

    /**
     * 缩放图片
     */
    protected void bitmapScale(float x, float y) {
        // 因为要将图片放大,所以要根据放大的尺寸重新创建Bitmap
        Bitmap afterBitmap = Bitmap.createBitmap(
                (int) (baseBitmap.getWidth() * x),
                (int) (baseBitmap.getHeight() * y), baseBitmap.getConfig());
        Canvas canvas = new Canvas(afterBitmap);
        // 初始化Matrix对象
        Matrix matrix = new Matrix();
        // 根据传入的参数设置缩放比例
        matrix.setScale(x, y);
        // 根据缩放比例,把图片draw到Canvas上
        canvas.drawBitmap(baseBitmap, matrix, paint);
        iv_after.setImageBitmap(afterBitmap);
    }

    /**
     * 倾斜图片
     */
    protected void bitmapSkew(float dx, float dy) {
        // 根据图片的倾斜比例,计算变换后图片的大小,
        Bitmap afterBitmap = Bitmap.createBitmap(baseBitmap.getWidth()
                + (int) (baseBitmap.getWidth() * dx), baseBitmap.getHeight()
                + (int) (baseBitmap.getHeight() * dy), baseBitmap.getConfig());
        Canvas canvas = new Canvas(afterBitmap);
        Matrix matrix = new Matrix();
        // 设置图片倾斜的比例
        matrix.setSkew(dx, dy);
        canvas.drawBitmap(baseBitmap, matrix, paint);
        iv_after.setImageBitmap(afterBitmap);
    }

    /**
     * 图片移动
     */
    protected void bitmapTranslate(float dx, float dy) {
        // 需要根据移动的距离来创建图片的拷贝图大小
        Bitmap afterBitmap = Bitmap.createBitmap(
                (int) (baseBitmap.getWidth() * dx),
                (int) (baseBitmap.getHeight() * dy), baseBitmap.getConfig());
        Canvas canvas = new Canvas(afterBitmap);
        Matrix matrix = new Matrix();
        // 设置移动的距离
        matrix.setTranslate(dx, dy);
        canvas.drawBitmap(baseBitmap, matrix, paint);
        iv_after.setImageBitmap(afterBitmap);
    }

    /**
     * 图片旋转
     */
    protected void bitmapRotate(float degrees) {
        // 创建一个和原图一样大小的图片
        Bitmap afterBitmap = Bitmap.createBitmap(baseBitmap.getWidth(),
                baseBitmap.getHeight(), baseBitmap.getConfig());
        Canvas canvas = new Canvas(afterBitmap);
        Matrix matrix = new Matrix();
        // 根据原图的中心位置旋转
        matrix.setRotate(degrees, baseBitmap.getWidth() / 2,
                baseBitmap.getHeight() / 2);
        canvas.drawBitmap(baseBitmap, matrix, paint);
        iv_after.setImageBitmap(afterBitmap);
    }

}

MainActivity.java

[转载]android开发教程进程与线程-Android开发资料下载-eoe Android开发者社区_Android开发论坛

mikel阅读(789)

[转载]【android开发教程】进程与线程-Android开发资料下载-eoe Android开发者社区_Android开发论坛.

引言

当应用程序的组件第一次运行时,Android将启动一个只有一个执行线程的Linux进程。默认,应用程序所有的组件运行在这个进程和线程中。然而,你可以安排组件运行在其他进程中,且你可以为进程衍生出其它线程。本文从下面几点来介绍Android的进程与线程:
  • 1、进程
  • 2、线程
    • 2.1、远程过程调用(Remote procedure calls,RPCs)
    • 2.2、线程安全方法


1、进程

组 件运行于哪个进程中由清单文件控制。组件元素—— <activity>、<service>、<receiver>、<provider>,都有一个 process属性可以指定组件运行在哪个进程中。这个属性可以设置为每个组件运行在自己的进程中,或者某些组件共享一个进程而其他的不共享。他们还可以 设置为不同应用程序的组件运行在同一个进程中——假设这些应用程序共享同一个Linux用户ID且被分配了同样的权 限。<application>元素也有process属性,为所有的组件设置一个默认值。
所 有的组件都在特定进程的主线程中实例化,且系统调用组件是由主线程派遣。不会为每个实例创建单独的线程,因此,对应这些调用的方法——诸如 View.onKeyDown()报告用用户的行为和生命周期通知,总是运行在进程的主线程中。这意味着,没有组件当被系统调用时应该执行很长时间或阻塞 操作(如网络操作或循环计算),因为这将阻塞进程中的其它组件。你可以为长操作衍生独立的线程。

public boolean onKeyDown(int keyCode,KeyEvent event):默认实现KeyEvent.Callback.onKeyMultiple(),当按下视图的KEYCODE_DPAD_CENTER或 KEYCODE_ENTER然后释放时执行,如果视图可用且可点击。

参数

keyCode-表示按钮被按下的键码,来自KeyEvent
event-定义了按钮动作的KeyEvent对象

返回值

如果你处理事件,返回true;如果你想下一个接收者处理事件,返回false。

当 内存剩余较小且其它进程请求较大内存并需要立即分配,Android要回收某些进程,进程中的应用程序组件会被销毁。当他们再次运行时,会重新开始一个进 程。当决定终结哪个进程时,Android会权衡他们对用户重要性的相对权值。例如,与运行在屏幕可见的活动进程相比(前台进程),它更容易关闭一个进 程,它的活动在屏幕是不可见(后台进程)。决定是否终结进程,取决于运行在进程中的组件状态。关于组件的状态,将在后面一篇——组件生命周期中介绍。2、 线程虽然你可能会将你的应用程序限制在一个进程中,但有时候你会需要衍生一个线程做一些后台工作。因为用户界面必须很快地响应用户的操作,所以活动寄宿的 线程不应该做一些耗时的操作如网络下载。任何不可能在短时间完成的操作应该分配到别的线程。线程在代码中是用标准的Java线程对象创建 的,Android提供了一些方便的类来管理线程——Looper用于在线程中运行消息循环、Handler用户处理消息、HandlerThread用 户设置一个消息循环的线程。

Looper类

该类用户在线程中运行消息循环。线程默认没有消息循环,可以在线程中调用prepare()创建一个运行循环;然后调用loop()处理消息直到循环结 束。大部分消息循环交互是通过Handler类。下面是一个典型的执行一个Looper线程的例子,分别使用prepare()和loop()创建一个初 始的Handler与Looper交互:

class LooperThread extends Thread {
public Handler mHandler;

public void run() {
Looper.prepare();

mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};

Looper.loop();
}
}

更多的关于Looper的信息及Handler、 HandlerThread请参阅相关资料。2.1、远程过程调用(Remote procedure calls,RPCs)Android有一个轻量级的远程过程调用机制——方法在本地调用却在远程(另外一个进程中)执行,结果返回给调用者。这需要将方 法调用和它伴随的数据分解为操作系统能够理解的层次,从本地进程和地址空间传输到远程进程和地址空间,并重新组装调用。返回值以相反方向传输。 Android提供了做这些工作的所有代码,这样我们可以专注于定义和执行RPC接口本身。一个RPC接口仅包含方法。所有的方法同步地执行(本地方法阻 塞直到远程方法执行完成),即使是没有返回值。简言之,该机制工作原理如下:首先,你用简单的IDL(interface definition language,接口定义语言)声明一个你想实现的RPC接口。从这个声明中,aidl工具生成一个Java接口定义,提供给本地和远程进程。它包含两 个内部类,如下图所示:


内部类有管理你用IDL定义的接口的远程过程调 用所需要的所有代码。这两个内部类都实现了IBinder接口。其中之一就是在本地由系统内部使用,你写代码可以忽略它。另外一个是Stub,扩展自 Binder类。除了用于有效地IPC(interprocess communication)调用的内部代码,内部类在RPC接口声明中还包含方法声明。你可以定义Stub的子类实现这些方法,如图中所示。通常情况 下,远程过程有一个服务管理(因为服务能通知系统关于进程和它连接的其它进程的信息)。它有由aidl工具生成的接口文件和Stub子类实现的RPC方 法。服务的客户端仅有由aidl工具生成的接口文件。下面介绍服务如何与它的客户端建立连接:
  • 服务的客户端(在本地端的)应该实现onServiceConnected() 和onServiceDisconnected() 方法,因此当与远程服务建立连接成功和断开连接是会通知它。然后调用bindService() 建立连接。
  • 服务的onBind()方法将实现为接受或拒绝连接,者取决于它接受到的意图(该意图传送到binServive())。如果连接被接受,它返回一个Stub子类的实例。
  • 如果服务接受连接,Android调用客户端的onServiceConnected()方法且传递给它一个IBinder对象,返回由服务管理的Stub子类的一个代理。通过代理,客户端可以调用远程服务。

这里只是简单地描述,省略了一些RPC机制的细节。你可以查阅相关资料或继续关注Android开发之 旅,后面将为你奉上。2.2、线程安全方法在一些情况下,你实现的方法可能会被不止一个线程调用,因此必须写成线程安全的。这对远程调用方法是正确的—— 如上一节讨论的RPC机制。当从IBinder进程中调用一个IBinder对象中实现的一个方法,这个方法在调用者的线程中执行。然而,当从别的进程中 调用,方法将在Android维护的IBinder进程中的线程池中选择一个执行,它不在进程的主线程中执行。例如,一个服务的onBind()方法在服 务进程的主线程中被调用,在onBind()返回的对象中执行的方法(例如,实现RPC方法的Stub子类)将在线程池中被调用。由于服务可以有一个以上 的客户端,所以同时可以有一个以上的线程在执行同一个IBinder方法。因此,IBinder的方法必须是线程安全的。同样,一个内容提供者可以接受其 它进程产生的数据请求。虽然ContentResolver 和 ContentProvider 类隐藏进程通信如何管理的,对应哪些请求的ContentResolver 方法——query()、insert()、delete()、update()、getType(),在内容提供者的进程的线程池中被调用,而不是在这 一进程的主线程中。因为这些方法可以同时从任意数量的线程中调用,他们也必须实现为线程安全的。

[转载]第二十六讲:Handler使用入门-Android新手入门-eoe Android开发者社区_Android开发论坛

mikel阅读(825)

[转载]第二十六讲:Handler使用入门-Android新手入门-eoe Android开发者社区_Android开发论坛.

本讲内容:Handler使用入门
当用户点击一个按钮时如果执行的是一个常耗时操作的话,处理不好会导致系统假死,用户体验很差,而Android则更进一步,如果任意一个Acitivity没有响应5秒钟以上就会被强制关闭,因此我们需要另外起动一个线程来处理长耗时操作,而主线程则不受其影响,在耗时操作完结发送消息给主线程,主线程再做相应处理。那么线程之间的消息传递和异步处理用的就是Handler。
下面我们通过一个模拟文件下载的这个长耗时操作来做个说明:
1、新建一个项目 Lesson27_Handler
2、在MainHandler.java中写如下面内容:
package android.basic.lesson27;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainHandler extends Activity {

//声明变量
private Button b1;
private ProgressDialog pd;

//定义Handler对象
private Handler handler =new Handler(){
@Override
//当有消息发送出来的时候就执行Handler的这个方法
public void handleMessage(Message msg){
super.handleMessage(msg);
//只要执行到这里就关闭对话框
pd.dismiss();
}
};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Resources res= this.getResources();
//查看UI组件所在的线程名
Log.i("tag", "onCreate()--&gt;"+Thread.currentThread().getName());

//定义UI组件
b1= (Button)findViewById(R.id.Button01);
//给按钮绑定单击事件监听器
b1.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
//点击按钮后去处理长耗时操作
processThread();
}
});
}

private void processThread(){

//构建一个下载进度条
pd= ProgressDialog.show(MainHandler.this, "下载文件", "正在下载……");
Log.i("tag", "processThread()--&gt;"+Thread.currentThread().getName());

new Thread(){

@Override
public void run(){
Log.i("tag", "run()--&gt;"+Thread.currentThread().getName());
//在新线程里执行长耗时方法
longTimeMethod();
//执行完毕后给handler发送一个空消息
handler.sendEmptyMessage(0);
}

}.start();
}

//模拟下载文件的长耗时方法
private void longTimeMethod(){
try {
Log.i("tag", "longTimeMethod--&gt;"+Thread.currentThread().getName());
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3、res/layout/main.xml的内容就省略了,你们可以根据程序运行截图和程序代码反推出来布局组件。
4、运行程序查看结果:
这个例子里,在辅助线程的run方法中执行长耗时操作,操作完毕后调用handler.sendEmptyMessage()方法,主线程中的Handler的 handleMessage()方法接受到这一消息,并做了就是关闭对话框的处理。
在接下来的例子里,让我们处理一些更复杂的操作来理解和练习Handler的使用方法。

[转载]如何使用Omnifocus做时间管理 1 相处哲学 | 小强的时间管理博客

mikel阅读(1033)

[转载]如何使用Omnifocus做时间管理 1 相处哲学 | 小强的时间管理博客.

Omnifocus(以下简称OF)蛮贵的,不过还好,老付送给我一份 :)

所以我从2008年底的时候就开始使用了,到现在已经5年,中间也尝试过Things、Doit.im,它们都很棒,但我和OF一直没有分开。

OF就像是我的一个老朋友:偶然的认识,慢慢的了解,在人际泛滥、人情冷暖的大环境中彼此信任和依赖。

照片

接下来请允许我分享和OF的相处哲学,一共有三点:

  • 两个身体,一个灵魂
  • 探索彼此的宝藏
  • 成熟内敛的性格

两个身体,一个灵魂

不要把提升行动力寄托在OF身上,就像不要把拥有幸福寄托在别人的身上一样

我们完全是单独的个体:OF有他自己的个性、优点、缺点,我自己也是一样

我们能够在一起是因为我们的灵魂相通:GTD

我是从2007年开始实践GTD方法的,一直到现在,OF是基于GTD方法开发出来的软件,没有多余的东西,也不能再缺少什么

所以,如果你不是GTD方法的实践者,OF不一定适合你,同样的,如果你只需要一个Todo List,那么OF也不适合你。

他们到底有何不同?

如果你认真和OF相处的话,他会随时告诉你:“下一步行动是什么。”是你的伙伴。

而Todo List类型的工具,比如说Clear,它只能告诉你:“还有这些事情要做。”是你的老板。

这里面我感觉区别巨大:

  • 伙伴会记得你交给他的所有事情,而老板不一定会,他只会说那句话:“还有这些事情要做!”(大部分的人只把自己认为重要的事情写到Todo List
  • 伙伴会和你一起分解项目、任务直到行动、一起用情境重新组织行动、一起回顾,贯穿做事的整个过程,而老板永远是那句话:“还有这些事情要做!”(Todo List类软件通常不支持无限层级,也不会区分项目、任务和行动的概念
  • 伙伴会和你一起成长,老板永远是那句话:“还有这些事情要做!”(Todo List类软件和你的成长无关,因为它背后没有系统,而GTD方法不仅有五个流程,还有六个高度,这是人生的高度,随着高度的爬升使用OF的方法会完全不同,看看项目文件夹的分类和情境分类就知道了。

两个身体,一个灵魂,这是和OF相处的第一个哲学。

NewImage

探索彼此的宝藏

OF在不断给我惊喜:

  • 一开始就被他的快速收集吸引:任何时候,Control+Command+空格就可以进入收集状态,不到1秒钟,并且从邮件、浏览器、编辑器可以直接选定–右键–发送到OF收集篮
  • 然后就是云同步:当我配齐iphone、macbook、ipad之后,才体验到云同步的便捷
  • 还有无限层级嵌套:我成为项目经理之后,同时管理5个小项目,每一个都不复杂,但要在它们当中迅速切换就比较麻烦了。这个时候我发现OF无线层级嵌套很有用。
  • 最近体验到的透视:这是OF最强大的功能,但以前真没什么感觉,几乎没用,最近我突然想只列出今天要做的事情,借此研究了一下透视功能,发现是可以做到的。
OF是一座宝藏,里面放的是你的成长。现实生活中也是这样,观其友而知其人。
在和OF相处的过程中,我的分类方式就产生了很大的变化:
  • 刚开始不怎么需要分类,其实就是按加强版的todo list去用
  • 后来开始按项目分类
  • 再后来按工作和生活分类
  • 现在按照幸福轮分类,并且和evernote同步

OF是一座宝藏,你也是!这是和OF相处的第二个哲学

NewImage

成熟内敛的性格

OF不华丽,不出众,但却有味道,耐看,有点像成熟、内敛的男人

我使用OF接近5年,从来没有崩溃过,虽然有时同步速度有点慢~

他这样的性格来自于他的家庭:Omni Group, 这是一个专门为苹果开发生产力的公司,创立于1989年,最早制作NeXT上面的软件,一共只有27位员工,全部持有公司股份,这已经能体现出这个家庭的 性格,OF的兄弟姐妹有:Omnifocus,Omniplan,Omnioutliner,Omnigraffle各个优雅、出众,多次获得苹果公司的 设计大奖。

对于一个朋友来说,你还奢求什么呢?

成熟、内敛,是和OF相处的第三个哲学。

NewImage

结语:

OF不是一个工具,是我的一个朋友:

  • 两个身体,一个灵魂
  • 探索彼此的宝藏
  • 成熟内敛的性格
这就是为什么我一直和OF在一起的原因。

这个系列文章是和@于亮Huntlive、@张昊Eric、IT毒龙等等大牛讨论的成果,还请大家多多指教!

小强打算这样写:

  • 首先写一篇我所理解的OF相处哲学
  • 然后不同工作类型的人,侧重点会不同,行政人员侧重收集,管理人员侧重组织,所以我虚拟出几个角色去分别诠释OF的使用
  • 每个角色都是按照这样的结构去写:角色特征–>关键流程–>技巧

希望对大家有用:)

NewImage

一些相关资源:

《工具控的福音-来自Omnifocus使用心得总结》来自@Oceannagirlhttp://www.douban.com/people/Oceannagirl/

《GTD和omnifocus的那些事儿》来自李小欠 :http://1banban.net/post/10164944860

《omnifocus系列教程》来自AsianEfficiency:http://www.asianefficiency.com/omnifocus/

[转载]如何使用Omnifocus做时间管理 2 清空收集篮 | 小强的时间管理博客

mikel阅读(980)

[转载]如何使用Omnifocus做时间管理 2 清空收集篮 | 小强的时间管理博客.

上一篇文章和大家分享了Omnifocus的使用哲学,这一篇邀请大家体验一下清空Omnifocus收件箱的感觉。

建议大家在收件箱里攒上一堆杂事,或者先花几分钟把大脑里的现在有的杂事收集下来,然后我们一起做清空。

我的收件箱里现在就有一堆杂事,因为我去参加了一个为期四天的培训,虽然像打乒乓球一样,很多事情都立即就处理掉了,但还是积攒下来一些,刚好用来演示清空。

这篇文章叫《如何使用omnifocus清空收集篮》,但其实和OF这种工具没有太大关系,清空收集篮的重点是明晰收件箱里的每一件杂事

幸运的是,现在看起来每一件杂事都可以初步分类到七个抽屉里面:

  • 垃圾:当时这件事吸引到我的注意力,但现在已经不了
  • 将来:我想做这件事,但现在还不想仔细考虑它
  • 参考资料:不解释
  • 行动:可以立即去做的事
  • 项目:需要规划、沟通,并且多个步骤才能完成的事
  • 日历:约会
  • 等待:授权出去,但我要负责的事

清空了收集篮并不意味着所有的事情都解决了,这个步骤意味着我们将用不同的方式和精力来处理它们

比如:

  • 垃圾:删除掉,释放精力
  • 将来:放到将来清单,每周回顾,释放精力
  • 参考资料:归类,释放精力
  • 行动:确定时间底线和情境,投入精力
  • 项目:进行规划和沟通,投入更多精力
  • 日历:放入日程表并设置提前提醒,释放精力
  • 等待:放入等待清单,不定时回顾,释放精力
我们会发现最后投入精力的只有行动和项目,其他的分类都是在释放精力
压力是不是小一点呢
下面是小强录制的视频:

========再扯点其他的========

我们通常会说:“GTD是无压工作的艺术”,那GTD为什么能让我们“没有压力”呢?压力又从何而来?

先回答后面一个问题,压力来自于对事情无法掌控的焦虑,就像迷路时一样,David Allen写的很明确。

GTD中的每一个步骤都可以帮助我们释放压力,但如果没有完全按照它说的做,就没有作用。

比如捕捉,如果能做到“完整捕捉”,那么会释放压力,如果是“随意捕捉”,那么就没有释放压力的效果。就像漏水的桶一样,哪怕有个很小的漏洞,都会感到焦虑。

比如明晰,如果能做到“找到下一步行动”,那么就会释放压力,如果是“接下来有很多行动”,那么就没有释放压力的效果。就像戴手表一样,戴一块手表你知道时间,戴三个表,就不知道时间了。

等等等等,还有很多,就像练习投篮一样,用正确的方法练习,才会日日精进。

但这还只是横向的,对于我的使命是什么?我要把事情做到什么样的地步?我有哪些责任需要照顾?这些问题,如果没有掌控感,就会仍然觉得压力很大。

话说回来,“没有压力”其实就和“战胜拖延”一样,是理想状态,这个时刻我们感觉不到压力,到了下个时刻压力可能又会回来,所以我建议不要刻意“追求”,而是“享受”没有压力时的状态。