- package com.example.xiutest;
import java.io.File;import java.util.ArrayList;import java.util.List;publicclassMainActivityextendsActivityimplementsOnClickListener,OnTouchListener{privateContext ctx;privateBoolean isFrist=true;privateImageView dargtool;privateint lastX;privateint lastY;privateint startTop;privateint startBottom;privateint startLeft;privateint startRight;@Overrideprotectedvoid onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ctx =this;dargtool=(ImageView)findViewById(R.id.dargtool);dargtool.setOnTouchListener(this);}@Overridepublicboolean onTouch(View v,MotionEvent event){switch(event.getAction()){caseMotionEvent.ACTION_MOVE:int dx =(int)event.getRawX()- lastX;int dy =(int)event.getRawY()- lastY;int left = v.getLeft()+ dx;int top = v.getTop()+ dy;int right = v.getRight()+ dx;int bottom = v.getBottom()+ dy;if(left <0){left =0;right = left + v.getWidth();}if(right >720){right =720;left = right - v.getWidth();}if(top <0){top =0;bottom = top + v.getHeight();}if(bottom >600){bottom =600;top = bottom - v.getHeight();mHandler.sendEmptyMessage(3);}v.layout(left, top, right, bottom);lastX =(int) event.getRawX();lastY =(int) event.getRawY();break;caseMotionEvent.ACTION_DOWN:if(isFrist){startTop=dargtool.getTop();startBottom=dargtool.getBottom();startLeft=dargtool.getLeft();startRight=dargtool.getRight();isFrist=false;}lastX =(int) event.getRawX();lastY =(int) event.getRawY();break;caseMotionEvent.ACTION_UP:v.layout(startLeft, startTop, startRight, startBottom);break;default:break;}returntrue;}}
可拖动的View控件
int dy =(int)event.getRawY()- lastY;获取事件的绝对位置的变化, 转移给相对于父控件的相对位置View聚焦
<TextViewandroid:id="@+id/mine_nickname"android:layout_width="wrap_content"android:layout_height="fill_parent"android:ellipsize="marquee"android:focusable="true"android:focusableInTouchMode="true"android:gravity="center"android:marqueeRepeatLimit="marquee_forever"android:scrollHorizontally="true"android:singleLine="true"android:text=""android:textColor="@color/hovn_index_room_name"android:textSize="@dimen/mine_info_name_size"/>
自定义的viewgroup允许添加子view
//设置是否能够调用自定义的布局,false是可以setWillNotDraw(false);//优先其子类控件而获取到焦点setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
View.requestLayout()和invalidate
View的略缩图
privateBitmap getViewBitmap(View view ){view.setDrawingCacheEnabled(true);Bitmap bitmap =null;try{if(null!= view.getDrawingCache()){bitmap =Bitmap.createScaledBitmap( view.getDrawingCache(),256,192,false);}else{Bitmap bitmapTmp =((BitmapDrawable)( getResources().getDrawable( R.drawable.syncompdetailcontent_background ))).getBitmap();}}catch(OutOfMemoryError e ){e.printStackTrace();}finally{view.setDrawingCacheEnabled(false);view.destroyDrawingCache();}return bitmap;}
/*** 把View绘制到Bitmap上* @param view 需要绘制的View* @param width 该View的宽度* @param height 该View的高度* @return 返回Bitmap对象* add by csj 13-11-6*/publicBitmap getViewBitmap(View comBitmap,int width,int height){Bitmap bitmap = null;if(comBitmap != null){comBitmap.clearFocus();comBitmap.setPressed(false);boolean willNotCache = comBitmap.willNotCacheDrawing();comBitmap.setWillNotCacheDrawing(false);// Reset the drawing cache background color to fully transparent// for the duration of this operationint color = comBitmap.getDrawingCacheBackgroundColor();comBitmap.setDrawingCacheBackgroundColor(0);float alpha = comBitmap.getAlpha();comBitmap.setAlpha(1.0f);if(color !=0){comBitmap.destroyDrawingCache();}int widthSpec =View.MeasureSpec.makeMeasureSpec(width,View.MeasureSpec.EXACTLY);int heightSpec =View.MeasureSpec.makeMeasureSpec(height,View.MeasureSpec.EXACTLY);comBitmap.measure(widthSpec, heightSpec);comBitmap.layout(0,0, width, height);comBitmap.buildDrawingCache();Bitmap cacheBitmap = comBitmap.getDrawingCache();if(cacheBitmap == null){Log.e("view.ProcessImageToBlur","failed getViewBitmap("+ comBitmap +")",newRuntimeException());return null;}bitmap =Bitmap.createBitmap(cacheBitmap);// Restore the viewcomBitmap.setAlpha(alpha);comBitmap.destroyDrawingCache();comBitmap.setWillNotCacheDrawing(willNotCache);comBitmap.setDrawingCacheBackgroundColor(color);}return bitmap;}
privateBitmap getViewBitmap(View v){v.clearFocus();v.setPressed(false);boolean willNotCache = v.willNotCacheDrawing();v.setWillNotCacheDrawing(false);// Reset the drawing cache background color to fully transparent// for the duration of this operationint color = v.getDrawingCacheBackgroundColor();v.setDrawingCacheBackgroundColor(0);if(color !=0){v.destroyDrawingCache();}v.buildDrawingCache();Bitmap cacheBitmap = v.getDrawingCache();if(cacheBitmap == null){Log.e("Folder","failed getViewBitmap("+ v +")",newRuntimeException());return null;}Bitmap bitmap =Bitmap.createBitmap(cacheBitmap);// Restore the viewv.destroyDrawingCache();v.setWillNotCacheDrawing(willNotCache);v.setDrawingCacheBackgroundColor(color);return bitmap;}
View view = mLauncher.getDragLayer();view.setDrawingCacheEnabled(true);Bitmap bitmap = view.getDrawingCache();
ViewGroup提高绘制性能
publicvoid setChildrenDrawingCacheEnabled(boolean enabled){final int count = getChildCount();for(int i =0; i < count; i++){final View view = getChildAt(i);view.setDrawingCacheEnabled(true);// Update the drawing cachesview.buildDrawingCache(true);}}
void clearChildrenCache(){final int count = getChildCount();for(int i =0; i < count; i++){final CellLayout layout =(CellLayout) getChildAt(i);layout.setChildrenDrawnWithCacheEnabled(false);}}
截屏代码实现
publicclassScreenShot{// 获取指定Activity的截屏,保存到png文件publicstaticBitmap takeScreenShot(Activity activity){// View是你需要截图的ViewView view = activity.getWindow().getDecorView();view.setDrawingCacheEnabled(true);view.buildDrawingCache();Bitmap b1 = view.getDrawingCache();// 获取状态栏高度Rect frame =newRect();activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);int statusBarHeight = frame.top;System.out.println(statusBarHeight);// 获取屏幕长和高int width = activity.getWindowManager().getDefaultDisplay().getWidth();int height = activity.getWindowManager().getDefaultDisplay().getHeight();// 去掉标题栏// Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);Bitmap b =Bitmap.createBitmap(b1,0, statusBarHeight, width, height- statusBarHeight);view.destroyDrawingCache();savePic(b,"/sdcard/screen_test.png");return b;}// 保存到sdcardpublicstaticvoid savePic(Bitmap b,String strFileName){FileOutputStream fos =null;try{fos =newFileOutputStream(strFileName);if(null!= fos){b.compress(Bitmap.CompressFormat.PNG,90, fos);fos.flush();fos.close();}}catch(FileNotFoundException e){e.printStackTrace();}catch(IOException e){e.printStackTrace();}}/*** 把View对象转换成bitmap* */publicstaticBitmap convertViewToBitmap(View view){view.measure(MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED));view.layout(0,0, view.getMeasuredWidth(), view.getMeasuredHeight());view.buildDrawingCache();Bitmap bitmap = view.getDrawingCache();if(bitmap !=null){System.out.println("这不是nullde1");Log.d("nullde1","nullde1");}else{System.out.println("这nullnulllnulnlul");}return bitmap;}// 程序入口1publicstaticvoid shoot(Activity a){ScreenShot.savePic(ScreenShot.takeScreenShot(a),"/sdcard/screen_test.png");}// 程序入口2publicstaticvoid shootView(View view){ScreenShot.savePic(ScreenShot.convertViewToBitmap(view),"sdcard/xx.png");}publicstaticBitmap getViewBitmap(View v){v.clearFocus();v.setPressed(false);boolean willNotCache = v.willNotCacheDrawing();v.setWillNotCacheDrawing(false);// Reset the drawing cache background color to fully transparent// for the duration of this operationint color = v.getDrawingCacheBackgroundColor();v.setDrawingCacheBackgroundColor(0);if(color !=0){v.destroyDrawingCache();}v.buildDrawingCache();Bitmap cacheBitmap = v.getDrawingCache();if(cacheBitmap ==null){Log.e("TTTTTTTTActivity","failed getViewBitmap("+ v +")",newRuntimeException());returnnull;}Bitmap bitmap =Bitmap.createBitmap(cacheBitmap);// Restore the viewv.destroyDrawingCache();v.setWillNotCacheDrawing(willNotCache);v.setDrawingCacheBackgroundColor(color);return bitmap;}/*** 截取scrollview的屏幕* **/publicstaticBitmap getBitmapByView(ScrollView scrollView){int h =0;Bitmap bitmap =null;// 获取listView实际高度for(int i =0; i < scrollView.getChildCount(); i++){h += scrollView.getChildAt(i).getHeight();scrollView.getChildAt(i).setBackgroundResource(R.drawable.bg3);}Log.d(TAG,"实际高度:"+ h);Log.d(TAG," 高度:"+ scrollView.getHeight());// 创建对应大小的bitmapbitmap =Bitmap.createBitmap(scrollView.getWidth(), h,Bitmap.Config.ARGB_8888);finalCanvas canvas =newCanvas(bitmap);scrollView.draw(canvas);// 测试输出FileOutputStream out =null;try{out =newFileOutputStream("/sdcard/screen_test.png");}catch(FileNotFoundException e){e.printStackTrace();}try{if(null!= out){bitmap.compress(Bitmap.CompressFormat.PNG,100, out);out.flush();out.close();}}catch(IOException e){// TODO: handle exception}return bitmap;}privatestaticString TAG ="Listview and ScrollView item 截图:";/*** 截图listview* **/publicstaticBitmap getbBitmap(ListView listView){int h =0;Bitmap bitmap =null;// 获取listView实际高度for(int i =0; i < listView.getChildCount(); i++){h += listView.getChildAt(i).getHeight();}Log.d(TAG,"实际高度:"+ h);Log.d(TAG,"list 高度:"+ listView.getHeight());// 创建对应大小的bitmapbitmap =Bitmap.createBitmap(listView.getWidth(), h,Bitmap.Config.ARGB_8888);finalCanvas canvas =newCanvas(bitmap);listView.draw(canvas);// 测试输出FileOutputStream out =null;try{out =newFileOutputStream("/sdcard/screen_test.png");}catch(FileNotFoundException e){e.printStackTrace();}try{if(null!= out){bitmap.compress(Bitmap.CompressFormat.PNG,100, out);out.flush();out.close();}}catch(IOException e){// TODO: handle exception}return bitmap;}}
view及其子类的LayoutParams的设置
LayoutParamsParam=(RelativeLayout.LayoutParams) live_broadcase.getLayoutParams();float live_broadcase_lenght=live_broadcase.getTextSize()*s[2].length();if(screen_width<live_broadcase_lenght){Param.setMargins(Param.leftMargin,Param.topMargin,(int)-live_broadcase_lenght+screen_width,Param.bottomMargin);live_broadcase.setLayoutParams(Param);}
view的ViewConfiguration
ViewConfiguration config =ViewConfiguration.get(context);mTouchSlop = config.getScaledTouchSlop();
代码控制布局
RelativeLayout container =newRelativeLayout(this);Button btn1 =newButton(this);btn1.setId(11);btn1.setText("上");Button btn2 =newButton(this);btn2.setId(12);btn2.setText("下");Button btn3 =newButton(this);btn3.setId(13);btn3.setText("左");Button btn4 =newButton(this);btn4.setId(14);btn4.setText("右");Button btn5 =newButton(this);btn5.setId(15);btn5.setText("中");RelativeLayout.LayoutParams lp1 =newRelativeLayout.LayoutParams(100,RelativeLayout.LayoutParams.WRAP_CONTENT);RelativeLayout.LayoutParams lp2 =newRelativeLayout.LayoutParams(lp1);RelativeLayout.LayoutParams lp3 =newRelativeLayout.LayoutParams(lp1);RelativeLayout.LayoutParams lp4 =newRelativeLayout.LayoutParams(lp1);RelativeLayout.LayoutParams lp5 =newRelativeLayout.LayoutParams(lp1);lp5.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE);lp1.addRule(RelativeLayout.ABOVE, btn5.getId());lp1.addRule(RelativeLayout.ALIGN_LEFT, btn5.getId());lp2.addRule(RelativeLayout.BELOW, btn5.getId());lp2.addRule(RelativeLayout.ALIGN_LEFT, btn5.getId());lp3.addRule(RelativeLayout.LEFT_OF, btn5.getId());lp3.addRule(RelativeLayout.ALIGN_BASELINE, btn5.getId());lp4.addRule(RelativeLayout.RIGHT_OF, btn5.getId());lp4.addRule(RelativeLayout.ALIGN_TOP, btn5.getId());container.addView(btn5, lp5);container.addView(btn1, lp1);container.addView(btn2, lp2);container.addView(btn3, lp3);container.addView(btn4, lp4);return container;
addView的理解
public void addView (View child, int index, ViewGroup.LayoutParams params)
这里最主要的参数就是index,标示的是希望将view增加到哪个view的下面。从刚才的布局代码片段看,以父布局relativelayout算起,
即
RelativeLayou index=0;
GridView index=1;
LinearLayout index=2;
你如果给index填写大于2的值将会报错。因为在当前父容器下,没有大于3的同级view
当然你还可以填写index=-1,-1的意思是,将view加到父容器中所有容器的最下面,也就是linearlayout的下面
footView一般调用addView(child, -1, params);
public void addView(View child) {addView(child, -1);}
根据不同的需求加载布局到当前界面,并且保证不找错xml的情况下加载布局里面的控件
<?xml version="1.0" encoding="utf-8"?><mergexmlns:android="http://schemas.android.com/apk/res/android"><FrameLayoutandroid:id="@+id/fl_inner"android:layout_width="wrap_content"android:layout_height="fill_parent"android:paddingBottom="@dimen/header_footer_top_bottom_padding"android:paddingLeft="@dimen/header_footer_left_right_padding"android:paddingRight="@dimen/header_footer_left_right_padding"android:paddingTop="@dimen/header_footer_top_bottom_padding"><ImageViewandroid:id="@+id/pull_to_refresh_image"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"/><ProgressBarandroid:id="@+id/pull_to_refresh_progress"style="?android:attr/progressBarStyleSmall"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:indeterminate="true"android:visibility="gone"/></FrameLayout></merge>
<?xml version="1.0" encoding="utf-8"?><mergexmlns:android="http://schemas.android.com/apk/res/android"><FrameLayoutandroid:id="@+id/fl_inner"android:layout_width="fill_parent"android:layout_height="wrap_content"android:paddingBottom="@dimen/header_footer_top_bottom_padding"android:paddingLeft="@dimen/header_footer_left_right_padding"android:paddingRight="@dimen/header_footer_left_right_padding"android:paddingTop="@dimen/header_footer_top_bottom_padding"><FrameLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="left|center_vertical"><ImageViewandroid:id="@+id/pull_to_refresh_image"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"/><ProgressBarandroid:id="@+id/pull_to_refresh_progress"style="?android:attr/progressBarStyleSmall"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:indeterminate="true"android:visibility="gone"/></FrameLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:gravity="center_horizontal"android:orientation="vertical"><TextViewandroid:id="@+id/pull_to_refresh_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:textAppearance="?android:attr/textAppearance"android:textStyle="bold"/><TextViewandroid:id="@+id/pull_to_refresh_sub_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:textAppearance="?android:attr/textAppearanceSmall"android:visibility="gone"/></LinearLayout></FrameLayout></merge>
public abstract class LoadingLayout extends FrameLayout implements ILoadingLayout {publicLoadingLayout(Context context,finalMode mode,finalOrientation scrollDirection,TypedArray attrs){super(context);mMode = mode;mScrollDirection = scrollDirection;switch(scrollDirection){case HORIZONTAL:LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_horizontal,this);break;case VERTICAL:default:LayoutInflater.from(context).inflate(R.layout.pull_to_refresh_header_vertical,this);break;}mInnerLayout =(FrameLayout) findViewById(R.id.fl_inner);mHeaderText =(TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_text);mHeaderProgress =(ProgressBar) mInnerLayout.findViewById(R.id.pull_to_refresh_progress);mSubHeaderText =(TextView) mInnerLayout.findViewById(R.id.pull_to_refresh_sub_text);mHeaderImage =(ImageView) mInnerLayout.findViewById(R.id.pull_to_refresh_image);
viewstub的理解
Android性能优化之一:ViewStub
ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View。虽然Android开发人员基本上都听说过,但是真正用的可能不多。
ViewStub可以理解成一个非常轻量级的View,与其他的控件一样,有着自己的属性及特定的方法。当ViewStub使用在布局文件中时,当程序inflate布局文件时,ViewStub本身也会被解析,且占据内存控件,但是与其他控件相比,主要区别体现在以下几点:
1.当布局文件inflate时,ViewStub控件虽然也占据内存,但是相相比于其他控件,ViewStub所占内存很小;
2.布局文件inflate时,ViewStub主要是作为一个“占位符”的性质,放置于view tree中,且ViewStub本身是不可见的。ViewStub中有一个layout属性,指向ViewStub本身可能被替换掉的布局文件,在一定时机时,通过viewStub.inflate()完成此过程;
3.ViewStub本身是不可见的,对ViewStub setVisibility(..)与其他控件不一样,ViewStub的setVisibility 成View.VISIBLE或INVISIBLE如果是首次使用,都会自动inflate其指向的布局文件,并替换ViewStub本身,再次使用则是相当于对其指向的布局文件设置可见性。
这里需要注意的是:
1.ViewStub之所以常称之为“延迟化加载”,是因为在教多数情况下,程序无需显示ViewStub所指向的布局文件,只有在特定的某些较少条件下,此时ViewStub所指向的布局文件才需要被inflate,且此布局文件直接将当前ViewStub替换掉,具体是通过viewStub.infalte()或viewStub.setVisibility(View.VISIBLE)来完成;
2.正确把握住ViewStub的应用场景非常重要,正如如1中所描述需求场景下,使用ViewStub可以优化布局;
3.对ViewStub的inflate操作只能进行一次,因为inflate的时候是将其指向的布局文件解析inflate并替换掉当前ViewStub本身(由此体现出了ViewStub“占位符”性质),一旦替换后,此时原来的布局文件中就没有ViewStub控件了,因此,如果多次对ViewStub进行infalte,会出现错误信息:ViewStub must have a non-null ViewGroup viewParent。
4.3中所讲到的ViewStub指向的布局文件解析inflate并替换掉当前ViewStub本身,并不是完全意义上的替换(与include标签还不太一样),替换时,布局文件的layout params是以ViewStub为准,其他布局属性是以布局文件自身为准。
下面看一下简单的需求场景:在listview显示列表数据时,可能会出现服务端一条数据都没有的情况,此时显示一个EmptyView,提示用户暂无数据。此时考虑到实际应用中EmptyView显示出来的机会相当小,因此,可以在布局文件中使用ViewStub站位,然后确实没有数据时才viewStub.infalte()。
相关部分代码如下:
1 public void showEmptyView() {
2 listview.setVisibility(View.GONE);
3 if (noDataView == null) {
4 ViewStub noDataViewStub = (ViewStub) view.findViewById(R.id.no_data_viewstub);
5 noDataView = noDataViewStub.inflate();
6 } else {
7 noDataView.setVisibility(View.VISIBLE);
8 }
9 }
1011 public void showListView(){
12 listview.setVisibility(View.VISIBLE);
13 if(noDataView != null){
14 noDataView.setVisibility(View.GONE);
15 }
16 }
特别需要注意的是对ViewStub是否已经inflate的判断。
在Listview Item中,有时候可能遇到如下场景:在不同的列表页item的布局一部分不同,但相对于整个item布局来说又不是很多,此时最常见的有如下两种处理:
1.对不同的部分都写出来,放到一个item文件中,然后逻辑分别处理不同部分的显示与否(View.VISIBLE和View.GONE);
2.对这两种不同的item整个部分都分别区分开,完全写成两个item文件,然后结合listView显示不同布局分别做逻辑处理(通过getItemType()等方式)。
以上两种处理方式其实都可以,第一种方式逻辑清晰,非常灵活,只是在一定程度上增加了内存和资源消耗。第二种方式是的布局文件有重复(虽然相同部分可以通过include,但是逻辑上还是有重复的),包括逻辑上处理的代码实质上的重复。一般对于有较大不同的item布局推荐采用此种方式。
有时候结合需求,可以在第一种方式的基础上,结合ViewStub“占位符”可以比较好的完成此类需求。也相当于是两种方式的一种折中形式,但同时兼顾了内存和资源消耗以及不同的布局逻辑控件。
在代码中新建一个控件对象,和布局控件(xml中的)的位置一样的
//m.setLayoutParams(lp);//RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(250, 250);//lp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);//lp.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);//lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);//m.setX(x);//int[] fromViewLocation = new int[2];//liveactivity.getLocationOnScreen(fromViewLocation);//m.setX(fromViewLocation[0]/2);//m.setY(fromViewLocation[1]/2);
android.view.ViewGroup.LayoutParams lp= live_gift_display.getLayoutParams();ImageView m=newImageView(this);m.setLayoutParams(lp);m.setScaleType(ScaleType.FIT_CENTER);m.setImageDrawable(d);liveactivity.addView(m);m.layout(live_gift_display.getLeft(), live_gift_display.getTop(), live_gift_display.getRight(), live_gift_display.getBottom());
改变控件的高和宽
RelativeLayout.LayoutParams linearParams =(RelativeLayout.LayoutParams) baseBtn.getLayoutParams();//取控件textView当前的布局参数linearParams.height = getResources().getDimensionPixelSize(R.dimen.height_20dp);// 控件的高强制设成20linearParams.width = getResources().getDimensionPixelSize(R.dimen.width_20dp);// 控件的宽强制设成30baseBtn.setLayoutParams(linearParams);
OnGlobalLayoutListener获得一个视图的高度
privateint mHeaderViewHeight;privateView mHeaderView;.....mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(newOnGlobalLayoutListener(){@Overridepublicvoid onGlobalLayout(){mHeaderViewHeight = mHeaderView.getHeight();mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);}});
ViewGroup为什么不会调用onDraw
onLayout的含义(ViewGroup:可布局的区域 view:布局的位置)
@Overrideprotected abstract void onLayout(boolean changed,int l,int t,int r,int b);
publicvoid layout(int l,int t,int r,int b);
