Leetao's Blog

Talk is cheap, show me the code

0%

获取combobox选中的值,文本

1
2
$('#com').combobox('getValue') //获取当前选中的值
$('#com').combobox('getText') //获取当前选中的文字

combotree设置默认值

1
$('#combotree').combotree('setValue',value);

禁用与启用combobox

1
2
$('#combobox').combobox('disable',true)
$('#combobox').combobox('enable')

combobox的隐藏与显示

1
2
$('#combobox + .combo').hide()
$('#combobox + .combo').show()

获取textarea的值

1
$('#textarea').val()

禁用与启用textarea

1
2
document.getElementById('textarea').disabled=true;
document.getElementById('textarea').disabled=false

获取textbox的值

1
$('#textbox').val()

禁用与启用textbox

1
2
$('#textbox').textbox('disable',true)
$('#textbox').textbox('enable')

linkbutton的禁用与启用

1
2
$('#linkbutton').linkbutton('disable');
$('#linkbutton').linkbutton('enable');

form的清空

1
$('#form').form('clear');

禁用整个form里面的输入框

1
2
$("#Form :input").attr("readonly", "readonly");
$("input").attr("readonly", "readonly");

validatebox的禁用与启用

前两种适用于单个的validatebox;

1
2
3
4
$("#id").attr("readonly", true); 
$("#id").removeAttr("readonly");
$("#id").attr("readonly", "readonly");
$("#id").removeAttr("readonly");

清空validatebox的值

1
$('#id').val("")

datebox禁用启用方法

1
2
$("#datebox").datebox('disable'); 
$("#datebox").datebox('enable');

datetimebox禁用启用方法

1
2
$("#datetimebox").datetimebox('disable');
$('#datetimebox').datatimebox('enable');

TextArea禁止拉动拖动改变大小

  1. 彻底禁用拖动:在sytle中添加resize:none
  2. 固定大小,右下角拖动图标依然存在
    1
    2
    3
    4
    width: x
    maxwidth: y
    height: mx
    maxheight: my

之前写Python的时候,用到了装饰器,然后不由自主想到了设计模式中的装饰模式,正好最近一直在看设计模式,就记录下自己的一些理解。如有错误,欢迎指正。

装饰模式

比较官方的定义是这样的

装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象

装饰,装饰嘛,很显然你只想让别人看见最终装饰的东西,并不像让别人看见你的装饰过程。打个比方说,你去餐馆吃饭,很明显主要是吃饭,当然光吃米饭,肯定难以下咽了,你想了想准备吃青椒肉丝盖浇饭,然后餐馆厨房开始做了,这个时候你想去厨房去瞧一瞧,你发现厨房门上贴着“非工作人员入内”,意思很明显嘛,餐馆并不希望我去参观他做盖浇饭的过程,谁知道中间有什么猫腻,最后呈现在我面前的就是我自己点的那份青椒肉丝盖浇饭,当然盖浇饭不止这一种还有番茄鸡蛋盖浇饭啊,鱼香肉丝盖浇饭啊。。。不过厨房加工的地方不让看。

类图是这样的:

可以把Component看作一个食物,ConcreteComponent看作米饭,Decorator则可以看作加工过程,ConcreteDecoratorA(B)就是各种食物素材啦。
对于Componet是无需知道Decorator存在的。
如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样如果只有一个ConcreteDecorator
,那么也没有必要建立一个单独的Decorator,而可以把Decorator和ConcreteDecorator的责任合并成一个类。

这个时候的类图,如下:

和这样

顺便说下starUML类图中部分符号的含义:

  1. 类 ( Class ) :三层矩形框表示,第一层类名,如果是抽象类,是用斜体表示的;第二层是字段和属性;第三层则是类方法,其中”+”表示该方法是public的,“-”表示private,“#”表示protected
  2. 继承类():用空心三角形+实现来表示

Talk is cheap,show me the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php
abstract class food
{
public $_name;
abstract public function cook();
}

//被装饰的类
class rice extends food
{
public function __construct()
{
$this->_name = 'rice';
}

public function cook()
{
return "cooked_rice";
}
}

//盖浇饭decorator
class fooddecorator extends food
{
public function __construct()
{
$this->_name = 'fooddecorator';
}

public function cook(){
return "cooking";
}
}

//青椒
class capsicum extends fooddecorator
{
public $_food;
public function __construct($food)
{
$this->_name = 'capsicum';
if($food instanceof food)
{
$this->_food = $food;
}else{
return false;
}
}

public function cook()
{
return $this->_food->cook()." cooked_capsicum";
}
}

//肉丝
class meat extends fooddecorator
{
public $_food;
public function __construct($food)
{
$this->_name = 'meat';
if($food instanceof food)
{
$this->_food = $food;
}else{
return false;
}
}

public function cook()
{
return $this->_food->cook()." cooked_meat";
}
}

//qr 青椒加饭 qjrs means 青椒肉丝
$rice = new rice();
//加青椒
$qr = new capsicum($rice);
//加肉
$qjrs = new meat($qr);

echo "fried green peppers:".$qjrs->cook();
?>

结果:

好像忘记加盐了0.0
装饰模式是围绕一个核心,然后动态装饰这个核心,很明显盖浇饭的核心是饭,在饭上加不同的菜,产生了不同的盖浇饭
这个时候估计有人说了,我不用装饰模式也可以实现着个过程啊

然后写了这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
abstract class food
{
public $_name;
abstract public function cook();
}

class rice extends food
{
public function __construct()
{
$this->_name = 'rice';
}

public function cook()
{
return " cooked_rice";
}
}

class capsicum extends food
{
public function __construct()
{
$this->_name = 'capsicum';
}

public function cook()
{
return " cooked_capsicum";
}
}

class meat extends food
{
public function __construct()
{
$this->_name = 'meat';
}

public function cook()
{
return " cooked_meat";
}
}

$rice = new rice();
$capsicum = new capsicum();
$meat = new meat();
echo "fried green peppers:".$rice->cook().$capsicum->cook().$meat->cook();
?>

结果很明显跟上面一样但是没有区别吗很明显第二种方法,第二种方法暴露了你做盖浇饭的顺序,就相当于顾客悄悄溜进厨房,看着厨师把盖浇饭做好了,见证了这一从无到有的过程,因此我们需要用装饰模式,将这加工处理的工程隐藏起来,只有这一个区别吗?很明显并不是,第二种方法三个子类处于同级,不分主次,但是不要忘了,顾客是去吃米饭的,之所以要了盖浇饭是为了让米饭更好吃,如果真的没有菜,做不成盖浇饭,只吃米顾客还是可以接受的,但是要是没有米,光有菜可不行,米饭是前提条件。要是觉得难以接受这个设定,就把盖浇饭换成各种类型的粥吧,绿豆粥,红薯粥。。。,要是少了米,还能叫粥吗。

最后做下简单的总结

装饰模式总结

1.装饰模式是向原有的类,动态的添加新的功能。
2.把类中的装饰功能从类中移去,是简化了原有类。
3.跟继承的区别,装饰模式是围绕着一个核心,在该核心存在的情况下去进行的,存在主次的关系,而继承所有子类处于同级
4.装饰模式的装饰顺序也是很重要,继承则不存在这种问题。比如说,穿衣服,你应该先穿内衣,再穿外套,而不是任意顺序。
5.多用组合,少用继承

简单工厂模式定义

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现

简单工厂的 UML 图

简单工厂模式中的各个角色以及相应职责:

  1. 简单工厂: 简单工厂模式的核心,由它负责创建所有的所有类的内部逻辑.即通过调用简单工厂的类方法并传递参数,然后由简单工厂创建对应的类
  2. 抽象产品: 简单工厂模式所创建的所有对象的父类,这里父类不一定非要接口,也可以使抽象类,它负责描述所有实例所共有的公共接口
  3. 具体产品:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类

具体实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public interface Operation{
/*
* 获取结果
*/
public function get();
}

/*
* 加法类
*/
class OperationAdd implements Operation{
private $_NumA;
private $_NumB;

public function __construct($num1,$num2) {
$this->_NumA = $num1;
$this->_NumB = $num2;
}

public function get() {
return ($this->_NumA + $this->_NumB);
}
}

class OperationSub implments Operation {
private $_NumA;
private $_NumB;

public function __construct($num1,$num2) {
$this->_NumA = $num1;
$this->_NumB = $num2;
}

public function get() {
return ($this->_NumA - $this->_NumB);
}

}

public class OperaFactory{

private $_results;
private $_opera;

public function __construct() {
$this->_results = 0;
}

public function Calculate($num1,$num2,$operator) {
swtich($operator) {
case '+':
$this->_opera = new OperationAdd($num1,$num2);
break;
case '-':
$this->_opera = new OperationSub($num1,$num2);
break;
default:
break;
}
$this->_results = $this->_opera->get();
return $this->_results;
}
}

优缺点

在讲述优缺点的之前,我们可以先思考一个问题,就当前的例子而言,如果我们需要添加一个 乘法的类,我们只需要定义一个类方法继承Operation这个接口,然后实现该方法,最后在OperaFactory中的Calculate中加一个新的分支
优点:
从上述例子以及简单的思考,不难看出通过简单工厂设计模式使得程序变得更加灵活,便于修改,并易于复用,降低了代码的耦合性
缺点:
如我们在代码所见那样,所有的创建逻辑都在OperaFactory中的Calculate,一旦其不能正常工作,整个系统都将收到影响

一个上下文相关的分享提供者

layout

ViewPager

ViewPage是Android拓展包v4包中的类,可以让用户左右切换当前的View,官方api的描述如下:

Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows.
ViewPager is most often used in conjunction with Fragment, which is a convenient way to supply and manage the lifecycle of each page. There are standard adapters implemented for using fragments with the ViewPager, which cover the most common use cases. These are FragmentPagerAdapter and FragmentStatePagerAdapter; each of these classes have simple code showing how to build a full user interface with them.

从这个描述中我们可以知道以下几点:

  1. ViewPager绝大多数情况下和Frament结合使用,并且提供了FragmentPagerAdapter 和 FragmentStatePagerAdapter
  2. ViewPager需要配合PagerAdaper使用,PagerAdapter的作用是产生展示view的页面

TextView

1
android:textAppearance="?android:textAppearanceMedium"

这是设置文字的外观,引用系统自带的一个外观, ? 表示系统是否有这种外观,否则使用默认的外观

1
android:lineSpacingMultiplier="1.1"

设置行间距的倍数

1
android:lineSpacingExtra = "7dp"

设置行间距

ImageView

1
2
3
4
5
6
7
8
android:scaleType="fitCenter" //使用 CENTER 方式缩放图像
android:scaleType="center" //在视图中使图像居中,不执行缩放
android:scaleType="centerCrop" //均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都大于等于 相应的视图坐标(负的内边距).图像则位于视图的中央
android:scaleType="centerInside" //均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都小于等于 相应的视图坐标(负的内边距)
android:scaleType="fitEnd" //使用 END 方式缩放图像
android:scaleType="fitStart" //使用 START 方式缩放图像
android:scaleType="fitXY" //使用 FILL 方式缩放图像
android:scaleType="matrix" //绘制时,使用图像矩阵方式缩放

这是将图片边界缩放,以适应视图边界时的可选项.可参阅
ImageView.ScaleType代码演示

MainActivity

setOnPageChangeListener

第68行:ViewPager的setOnPageChangeListener弃用
setOnPageChangeListener 改为 addOnpageChangeListener
具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Set a listener that will be invoked whenever the page changes or is incrementally
* scrolled. See OnPageChangeListener.
*
* @param listener Listener to set
*
* @deprecated Use addOnPageChangeListener(OnPageChangeListener)
* and removeOnPageChangeListener(OnPageChangeListener) instead.
*/
@Deprecated
public void setOnPageChangeListener(OnPageChangeListener listener) {
mOnPageChangeListener = listener;
}

其含义就是设置一个监听器用来监控页面改变或者递增的滚动.

OnPageChangeListener

OnPageChangeListener是一个接口,需要去自行实现
具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Callback interface for responding to changing state of the selected page.
*/
public interface OnPageChangeListener {

/**
* This method will be invoked when the current page is scrolled, either as part
* of a programmatically initiated smooth scroll or a user initiated touch scroll.
*
* @param position Position index of the first page currently being displayed.
* Page position+1 will be visible if positionOffset is nonzero.
* @param positionOffset Value from [0, 1) indicating the offset from the page at position.
* @param positionOffsetPixels Value in pixels indicating the offset from position.
*/
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);

/**
* This method will be invoked when a new page becomes selected. Animation is not
* necessarily complete.
*
* @param position Position index of the new selected page.
*/
public void onPageSelected(int position);

/**
* Called when the scroll state changes. Useful for discovering when the user
* begins dragging, when the pager is automatically settling to the current page,
* or when it is fully stopped/idle.
*
* @param state The new scroll state.
* @see ViewPager#SCROLL_STATE_IDLE
* @see ViewPager#SCROLL_STATE_DRAGGING
* @see ViewPager#SCROLL_STATE_SETTLING
*/
public void onPageScrollStateChanged(int state);
}

从源码可以看出该接口是当选中页面状态改变时做出响应的,需要实现依次三个方法,三个方法分别对应着onPageScrolled(int position, float positionOffset, int positionOffsetPixels)(当页面滚动的时候),onPageSelected(int position)(当页面被选的时候),onPageScrollStateChanged(int state)(当页面滚动状态改变的时候)

PagerAdapter

官方api的说明:

Base class providing the adapter to populate pages inside of a ViewPager.You will most likely want to use a more
specific implementation of this, such as android.support.v4.app.FragmentPagerAdapter or
android.support.v4.app.FragmentStatePagerAdapter.

大致意思就是提供一个填充ViewPager中的页面内容的适配器.然后可能使用FragmentPagerAdapter和FragmentStatePagerAdapter可能性更高.

当继承PageAdapter的是否,需要重写以下的方法:

  1. instantiateItem(ViewGroup, int)
  2. destroyItem(ViewGroup, int, Object)
  3. getCount()
  4. isViewFromObject(View, Object)

具体源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* Create the page for the given position. The adapter is responsible
* for adding the view to the container given here, although it only
* must ensure this is done by the time it returns from finishUpdate(ViewGroup).
*
* @param container The containing View in which the page will be shown.
* @param position The page position to be instantiated.
* @return Returns an Object representing the new page. This does not
* need to be a View, but can be some other container of the page.
*
* @deprecated Use instantiateItem(ViewGroup, int)
*/
@Deprecated
public Object instantiateItem(View container, int position) {
throw new UnsupportedOperationException(
"Required method instantiateItem was not overridden");
}

/**
* Remove a page for the given position. The adapter is responsible
* for removing the view from its container, although it only must ensure
* this is done by the time it returns from finishUpdate(View).
*
* @param container The containing View from which the page will be removed.
* @param position The page position to be removed.
* @param object The same object that was returned by
* instantiateItem(View, int).
*
* @deprecated Use destroyItem(ViewGroup, int, Object)
*/
@Deprecated
public void destroyItem(View container, int position, Object object) {
throw new UnsupportedOperationException("Required method destroyItem was not overridden");
}

/**
* Return the number of views available.
*/
public abstract int getCount();

/**
* Determines whether a page View is associated with a specific key object
* as returned by instantiateItem(ViewGroup, int). This method is
* required for a PagerAdapter to function properly.
*
* @param view Page View to check for association with object
* @param object Object to check for association with view
* @return true if view is associated with the key object object
*/
public abstract boolean isViewFromObject(View view, Object object);

根据源码说的注释说明,可以得知:

  1. **instantiateItem(View container, int position)*该方法是在指定位置创建相应的页面,其中参数container*是展示页面中的view,参数position页面被实例化的位置,不过该方法现在已经被弃用,改用为instantiateItem(ViewGroup container, int position)
  2. **destroyItem(View container, int position, Object object)*该方法是移除指定位置的页面,其中参数container*是将要被移走页面的view,参数position是将要被移除页面的位置,参数object是由instantiateItem(View, int)返回的对象,该方法也被弃用,改用为destroyItem(ViewGroup, int, Object)
  3. **getCount()**该方法这是返回可以获取到的view数量
  4. isViewFromObject(View view, Object object) 判断当前view跟由instantiateItem(ViewGroup, int)返回的对象是否有关联,如果有则返回true,参数view需要校验的view,参数object需要校验的对象

LayoutInflater

layoutInflater其作用类似findViewById(),不同点则是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等).
具体作用:

  1. 对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入
  2. 对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素

LayoutInflater 是一个抽象类,在文档中如下声明:

1
public abstract class LayoutInflater extends Object

获得 LayoutInflater 实例的三种方式:

  1. LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater()
  2. LayoutInflater inflater = LayoutInflater.from(context);
  3. LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

LayoutInflater的inflate方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public View inflate(int resource, ViewGroup root) {
throw new RuntimeException("Stub!");
}

public View inflate(XmlPullParser parser, ViewGroup root) {
throw new RuntimeException("Stub!");
}

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
throw new RuntimeException("Stub!");
}

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
throw new RuntimeException("Stub!");
}

其返回值均为view,但是值得注意的是:inflater 是用来找 res/layout 下的 xml 布局文件,并且实例化;findViewById() 是找具体 xml 布局文件中的具体 widget 控件(如:Button、TextView 等

ShareActionProvider

官网api说明:

Provides a share action, which is suitable for an activity’s app bar. Creates views that enable data sharing. If the provider appears in the overflow menu, it creates a submenu with the appropriate sharing actions.

从上述描述我们可以ShareActionProvider其实会提供一个分享的按钮.如果分享按钮出现在溢出菜单,它会创建一个合适的子菜单

onCreateOptionsMenu

1
2
3
public boolean onCreateOptionsMenu(Menu menu) {
throw new RuntimeException("Stub!");
}

此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例.返回true则显示该menu,false 则不显示,只会在第一次初始化菜单时调用.


Activity菜单机制
Activity有一套机制来实现对菜单的管理,方法如下:

  1. public boolean onCreateOptionsMenu(Menu menu)
  2. public boolean onPrepareOptionsMenu(Menu menu) 在onCreateOptionsMenu执行后,菜单被显示前调用;如果菜单已经被创建,则在菜单显示前被调用.同样的,返回true则显示该menu,false 则不显示;(可以通过此方法动态的改变菜单的状态,比如加载不同的菜单等)
  3. public void onOptionsMenuClosed(Menu menu) 每次菜单被关闭时调用.(菜单被关闭有三种情形,menu按钮被再次点击,back按钮被点击或者用户选择了某一个菜单项)
  4. public boolean onOptionsItemSelected(MenuItem item) 菜单项被点击时调用,也就是菜单项的监听方法