- 浏览: 21998 次
- 性别:
- 来自: 北京
文章分类
最新评论
最近在研究android 版本的win8效果,只牵强实现了一部分。
1.自定义一个view,做为要移动和展示用。
package com.shao.test;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
public class MyView2 extends View{
private int alpha = 250;
private boolean pressed = false;
static final int NONE = 0;
static final int DRAG = 1; //拖动中
static final int ZOOM = 2; //缩放中
static final int BIGGER = 3; //放大ing
static final int SMALLER = 4; //缩小ing
private int mode = NONE; //当前的事件
private float beforeLenght; //两触点距离
private float afterLenght; //两触点距离
private float scale = 0.04f; //缩放的比例 X Y方向都是这个值 越大缩放的越快
private int screenW;
private int screenH;
/*处理拖动 变量 */
private int start_x;
private int start_y;
private int stop_x ;
private int stop_y ;
private int res_id;
private TranslateAnimation trans; //处理超出边界的动画
private int mX;
private int mY;
private int mWidth;
private int mHeight;
private static int mStartX;
private static int mStartY;
private static int mEndX;
private static int mEndY;
private static int isTouchID=-1;
public MyView2(Context context) {
super(context);
}
public MyView2(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyView2(Context context,int w,int h,int res)
{
super(context);
this.setPadding(0, 0, 0, 0);
screenW = w;
screenH = h;
res_id = res;
}
public MyView2(Context context,int w,int h)
{
super(context);
this.setPadding(0, 0, 0, 0);
screenW = w;
screenH = h;
}
Matrix m;
public void show()
{
new Thread(){
public void run() {
int time = 2000;
try
{
pressed = true;
while(time>0)
{
Thread.sleep(200);
time -= 200;
alpha-= 25;
postInvalidate();
}
pressed = false;
}
catch (Exception e)
{
e.printStackTrace();
}
};
}.start();
}
/**
* 就算两点间的距离
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
show();
isTouchID = 1;
mode = DRAG;
stop_x = (int) event.getRawX();
stop_y = (int) event.getRawY();
start_x = (int) event.getX();
start_y = stop_y - this.getTop();
mEndX = stop_x;
mEndY = stop_y;
mStartX = start_x;
mStartY = start_y;
if(event.getPointerCount()==2)
beforeLenght = spacing(event);
break;
case MotionEvent.ACTION_POINTER_DOWN:
isTouchID = 1;
if (spacing(event) > 10f) {
mode = ZOOM;
beforeLenght = spacing(event);
}
break;
case MotionEvent.ACTION_UP:
isTouchID = 2;
/*判断是否超出范围 并处理*/
int disX = 0;
int disY = 0;
if(getHeight()<=screenH || this.getTop()<0)
{
if(this.getTop()<0 )
{
int dis = getTop();
this.layout(this.getLeft(), 0, this.getRight(), 0 + this.getHeight());
disY = dis - getTop();
}
else if(this.getBottom()>screenH)
{
disY = getHeight()- screenH+getTop();
this.layout(this.getLeft(), screenH-getHeight(), this.getRight(), screenH);
}
}
if(getWidth()<=screenW)
{
if(this.getLeft()<0)
{
disX = getLeft();
this.layout(0, this.getTop(), 0+getWidth(), this.getBottom());
}
else if(this.getRight()>screenW)
{
disX = getWidth()-screenW+getLeft();
this.layout(screenW-getWidth(), this.getTop(), screenW, this.getBottom());
}
}
if(disX!=0 || disY!=0)
{
trans = new TranslateAnimation(disX, 0, disY, 0);
trans.setDuration(500);
this.startAnimation(trans);
}
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
isTouchID = 3;
/*处理拖动*/
if (mode == DRAG) {
if(Math.abs(stop_x-start_x-getLeft())<88 && Math.abs(stop_y - start_y-getTop())<85)
{
this.setPosition(stop_x - start_x, stop_y - start_y, stop_x + this.getWidth() - start_x, stop_y - start_y + this.getHeight());
stop_x = (int) event.getRawX();
stop_y = (int) event.getRawY();
}
}
/*处理缩放*/
else if (mode == ZOOM) {
if(spacing(event)>10f)
{
afterLenght = spacing(event);
float gapLenght = afterLenght - beforeLenght;
if(gapLenght == 0) {
break;
}
else if(Math.abs(gapLenght)>5f)
{
if(gapLenght>0) {
this.setScale(scale,BIGGER);
}else {
this.setScale(scale,SMALLER);
}
beforeLenght = afterLenght;
}
}
}
break;
}
return true;
/*
if(event.getAction() == MotionEvent.ACTION_DOWN)
show();
return false;*/
}
@Override
protected void onDraw(Canvas canvas)
{
Paint p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(10);
BitmapDrawable bd=(BitmapDrawable) getBackground();
//BitmapDrawable bd=null ;//= (BitmapDrawable)getResources();
//BitmapDrawable bd = (BitmapDrawable) getDrawable();
if(bd!=null)
{
canvas.drawBitmap(imageScale(bd.getBitmap(), 107, 113), 21,18, p);
}
canvas.drawBitmap(BitmapFactory.decodeResource(getContext().getResources(), res_id), 0, 0, p);
if(isPressed())
{
canvas.drawRect(5,5,140,140,p);
}
/*
if(pressed)
{
p.setAlpha(alpha);
canvas.drawRect(5,5,140,140,p);
}*/
}
public static Bitmap imageScale(Bitmap bitmap, int dst_w, int dst_h){
int src_w = bitmap.getWidth();
int src_h = bitmap.getHeight();
float scale_w = ((float)dst_w)/src_w;
float scale_h = ((float)dst_h)/src_h;
Matrix matrix = new Matrix();
matrix.postScale(scale_w, scale_h);
Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, src_w, src_h, matrix, true);
return dstbmp;
}
/**
* 实现处理缩放
*/
private void setScale(float temp,int flag) {
/*
if(flag==BIGGER) {
this.setFrame(this.getLeft()-(int)(temp*this.getWidth()),
this.getTop()-(int)(temp*this.getHeight()),
this.getRight()+(int)(temp*this.getWidth()),
this.getBottom()+(int)(temp*this.getHeight()));
}else if(flag==SMALLER){
this.setFrame(this.getLeft()+(int)(temp*this.getWidth()),
this.getTop()+(int)(temp*this.getHeight()),
this.getRight()-(int)(temp*this.getWidth()),
this.getBottom()-(int)(temp*this.getHeight()));
} */
}
/**
* 实现处理拖动
*/
public void setPosition(int left,int top,int right,int bottom) {
postInvalidate();
this.layout(left,top,right,bottom);
invalidate();
}
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
Log.i("shao1","onlayout -left"+left+" top="+top+" right="+right+" bottom="+bottom);
mX=left;
mY=top;
mWidth=right;
mHeight=bottom;
super.onLayout(changed, left, top, right, bottom);
}
public static int getDirection(){
int x = mEndX -mStartX;//
int y = mEndY -mStartY;//
//限制必须得划过屏幕的1/3才能算划过
// float x_limit = screen.widthPixels / 3;
// float y_limit = screen.heightPixels / 3;
int x_limit = 20;
int y_limit = 20;
int x_abs = Math.abs(x);
int y_abs = Math.abs(y);
if(x_abs >= y_abs){
//gesture left or right
if(x > x_limit || x < -x_limit){
if(x>0){
//right
Log.i("shao","right-----------");
return 0;
// show("right");
}else if(x<0){
//left
Log.i("shao","left-----------");
return 1;
}
}
}else{
//gesture down or up
if(y> y_limit || y < -y_limit){
if(y>0){
//down
Log.i("shao","down-----------");
return 2;
}else if(y<0){
//up
Log.i("shao","up-----------");
return 3;
}
}
}
return 0;
}
public int[] getChangePosition(){
int retValue[]={mX,mY,mWidth,mHeight};
return retValue;
}
public int touchId(){
//Log.i("shao"," istouch ="+isTouchID);
return isTouchID;
}
public int[][] getLocation(int index) {
int [][] result =null;
for(int i=0;i<position.length;i++){
if(i==index){
for(int j=0;j<4;j++){
result[0][j]=position[index][j];
}
break;
}
}
return result;
}
public void setLocation(int index, int[] newposition) {
for(int i=0;i<position.length;i++){
if(i==index){
for(int j=0;j<4;j++){
position[index][j]=newposition[j];
}
break;
}
}
}
public int[][] position =
{
{
0,0,200,400
},
{
200, 0, 800, 200
},
{
200, 200, 800, 400
}
};
}
待续.....
1.自定义一个view,做为要移动和展示用。
package com.shao.test;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
public class MyView2 extends View{
private int alpha = 250;
private boolean pressed = false;
static final int NONE = 0;
static final int DRAG = 1; //拖动中
static final int ZOOM = 2; //缩放中
static final int BIGGER = 3; //放大ing
static final int SMALLER = 4; //缩小ing
private int mode = NONE; //当前的事件
private float beforeLenght; //两触点距离
private float afterLenght; //两触点距离
private float scale = 0.04f; //缩放的比例 X Y方向都是这个值 越大缩放的越快
private int screenW;
private int screenH;
/*处理拖动 变量 */
private int start_x;
private int start_y;
private int stop_x ;
private int stop_y ;
private int res_id;
private TranslateAnimation trans; //处理超出边界的动画
private int mX;
private int mY;
private int mWidth;
private int mHeight;
private static int mStartX;
private static int mStartY;
private static int mEndX;
private static int mEndY;
private static int isTouchID=-1;
public MyView2(Context context) {
super(context);
}
public MyView2(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyView2(Context context,int w,int h,int res)
{
super(context);
this.setPadding(0, 0, 0, 0);
screenW = w;
screenH = h;
res_id = res;
}
public MyView2(Context context,int w,int h)
{
super(context);
this.setPadding(0, 0, 0, 0);
screenW = w;
screenH = h;
}
Matrix m;
public void show()
{
new Thread(){
public void run() {
int time = 2000;
try
{
pressed = true;
while(time>0)
{
Thread.sleep(200);
time -= 200;
alpha-= 25;
postInvalidate();
}
pressed = false;
}
catch (Exception e)
{
e.printStackTrace();
}
};
}.start();
}
/**
* 就算两点间的距离
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
show();
isTouchID = 1;
mode = DRAG;
stop_x = (int) event.getRawX();
stop_y = (int) event.getRawY();
start_x = (int) event.getX();
start_y = stop_y - this.getTop();
mEndX = stop_x;
mEndY = stop_y;
mStartX = start_x;
mStartY = start_y;
if(event.getPointerCount()==2)
beforeLenght = spacing(event);
break;
case MotionEvent.ACTION_POINTER_DOWN:
isTouchID = 1;
if (spacing(event) > 10f) {
mode = ZOOM;
beforeLenght = spacing(event);
}
break;
case MotionEvent.ACTION_UP:
isTouchID = 2;
/*判断是否超出范围 并处理*/
int disX = 0;
int disY = 0;
if(getHeight()<=screenH || this.getTop()<0)
{
if(this.getTop()<0 )
{
int dis = getTop();
this.layout(this.getLeft(), 0, this.getRight(), 0 + this.getHeight());
disY = dis - getTop();
}
else if(this.getBottom()>screenH)
{
disY = getHeight()- screenH+getTop();
this.layout(this.getLeft(), screenH-getHeight(), this.getRight(), screenH);
}
}
if(getWidth()<=screenW)
{
if(this.getLeft()<0)
{
disX = getLeft();
this.layout(0, this.getTop(), 0+getWidth(), this.getBottom());
}
else if(this.getRight()>screenW)
{
disX = getWidth()-screenW+getLeft();
this.layout(screenW-getWidth(), this.getTop(), screenW, this.getBottom());
}
}
if(disX!=0 || disY!=0)
{
trans = new TranslateAnimation(disX, 0, disY, 0);
trans.setDuration(500);
this.startAnimation(trans);
}
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
isTouchID = 3;
/*处理拖动*/
if (mode == DRAG) {
if(Math.abs(stop_x-start_x-getLeft())<88 && Math.abs(stop_y - start_y-getTop())<85)
{
this.setPosition(stop_x - start_x, stop_y - start_y, stop_x + this.getWidth() - start_x, stop_y - start_y + this.getHeight());
stop_x = (int) event.getRawX();
stop_y = (int) event.getRawY();
}
}
/*处理缩放*/
else if (mode == ZOOM) {
if(spacing(event)>10f)
{
afterLenght = spacing(event);
float gapLenght = afterLenght - beforeLenght;
if(gapLenght == 0) {
break;
}
else if(Math.abs(gapLenght)>5f)
{
if(gapLenght>0) {
this.setScale(scale,BIGGER);
}else {
this.setScale(scale,SMALLER);
}
beforeLenght = afterLenght;
}
}
}
break;
}
return true;
/*
if(event.getAction() == MotionEvent.ACTION_DOWN)
show();
return false;*/
}
@Override
protected void onDraw(Canvas canvas)
{
Paint p = new Paint();
p.setColor(Color.WHITE);
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(10);
BitmapDrawable bd=(BitmapDrawable) getBackground();
//BitmapDrawable bd=null ;//= (BitmapDrawable)getResources();
//BitmapDrawable bd = (BitmapDrawable) getDrawable();
if(bd!=null)
{
canvas.drawBitmap(imageScale(bd.getBitmap(), 107, 113), 21,18, p);
}
canvas.drawBitmap(BitmapFactory.decodeResource(getContext().getResources(), res_id), 0, 0, p);
if(isPressed())
{
canvas.drawRect(5,5,140,140,p);
}
/*
if(pressed)
{
p.setAlpha(alpha);
canvas.drawRect(5,5,140,140,p);
}*/
}
public static Bitmap imageScale(Bitmap bitmap, int dst_w, int dst_h){
int src_w = bitmap.getWidth();
int src_h = bitmap.getHeight();
float scale_w = ((float)dst_w)/src_w;
float scale_h = ((float)dst_h)/src_h;
Matrix matrix = new Matrix();
matrix.postScale(scale_w, scale_h);
Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, src_w, src_h, matrix, true);
return dstbmp;
}
/**
* 实现处理缩放
*/
private void setScale(float temp,int flag) {
/*
if(flag==BIGGER) {
this.setFrame(this.getLeft()-(int)(temp*this.getWidth()),
this.getTop()-(int)(temp*this.getHeight()),
this.getRight()+(int)(temp*this.getWidth()),
this.getBottom()+(int)(temp*this.getHeight()));
}else if(flag==SMALLER){
this.setFrame(this.getLeft()+(int)(temp*this.getWidth()),
this.getTop()+(int)(temp*this.getHeight()),
this.getRight()-(int)(temp*this.getWidth()),
this.getBottom()-(int)(temp*this.getHeight()));
} */
}
/**
* 实现处理拖动
*/
public void setPosition(int left,int top,int right,int bottom) {
postInvalidate();
this.layout(left,top,right,bottom);
invalidate();
}
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
Log.i("shao1","onlayout -left"+left+" top="+top+" right="+right+" bottom="+bottom);
mX=left;
mY=top;
mWidth=right;
mHeight=bottom;
super.onLayout(changed, left, top, right, bottom);
}
public static int getDirection(){
int x = mEndX -mStartX;//
int y = mEndY -mStartY;//
//限制必须得划过屏幕的1/3才能算划过
// float x_limit = screen.widthPixels / 3;
// float y_limit = screen.heightPixels / 3;
int x_limit = 20;
int y_limit = 20;
int x_abs = Math.abs(x);
int y_abs = Math.abs(y);
if(x_abs >= y_abs){
//gesture left or right
if(x > x_limit || x < -x_limit){
if(x>0){
//right
Log.i("shao","right-----------");
return 0;
// show("right");
}else if(x<0){
//left
Log.i("shao","left-----------");
return 1;
}
}
}else{
//gesture down or up
if(y> y_limit || y < -y_limit){
if(y>0){
//down
Log.i("shao","down-----------");
return 2;
}else if(y<0){
//up
Log.i("shao","up-----------");
return 3;
}
}
}
return 0;
}
public int[] getChangePosition(){
int retValue[]={mX,mY,mWidth,mHeight};
return retValue;
}
public int touchId(){
//Log.i("shao"," istouch ="+isTouchID);
return isTouchID;
}
public int[][] getLocation(int index) {
int [][] result =null;
for(int i=0;i<position.length;i++){
if(i==index){
for(int j=0;j<4;j++){
result[0][j]=position[index][j];
}
break;
}
}
return result;
}
public void setLocation(int index, int[] newposition) {
for(int i=0;i<position.length;i++){
if(i==index){
for(int j=0;j<4;j++){
position[index][j]=newposition[j];
}
break;
}
}
}
public int[][] position =
{
{
0,0,200,400
},
{
200, 0, 800, 200
},
{
200, 200, 800, 400
}
};
}
待续.....
发表评论
-
AsyncImageLoader
2013-07-31 21:37 0非原著,节选自http://code.google.com/p ... -
ubuntu 12.04驱动开发环境配置
2013-05-04 00:46 21791.在终端运行#uname-r查看现有的内核的版本,本人ubu ... -
android取得收藏夹的联系人
2012-06-06 18:43 1806摘自:http://blog.csdn.net/qiaonin ... -
Android 删除手机联系人,添加手机联系人,更新手机联系人信息
2012-05-21 21:25 3005添加联系人 private void addContact ... -
android源码下载以及编译
2012-02-25 23:23 1794redhat linux 一、下载并编译安装git wge ... -
android底层开发
2012-02-24 16:31 1041·Android开发:如何实现TCP和UDP传输 http:/ ... -
android adb shell常用命令
2012-02-20 18:20 6899最进学到了adb工具的一些小技巧,记录在此。操作系统是wind ... -
android取得json数据
2011-11-18 13:04 1291步骤一:页面返回JSON数据。 对本空间日志“php和AJA ...
相关推荐
- 导航到解压后的驱动文件夹,通常包含一个名为"android_winusb.inf"的文件,选择并确认安装。 2. ADB基本用法: - 安装完驱动后,可以在命令提示符或PowerShell中使用ADB命令。首先,需要将设备通过USB连接到...
【Android开发资料合辑】是针对Android开发者提供的一份综合性的学习资源集合,它包含了从基础到进阶的各种主题,旨在帮助开发者全面掌握Android开发技术。以下是对这些文档的详细解读: 1. **《eoe特刊》Windows ...
【作品名称】:基于ncnn框架搭建win及android端的MTCNN人脸检测工程 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】:...
判断是否节假日 然后执行adb命令 打开钉钉使用快速打卡(此处需要电脑一直连接一台android手机,此处适用于android开发) 安装pyinstalle pip install pyinstaller pyinstaller -F -w -i dingding.ico dingding.py win...
在探讨“mas android视频”这一主题时,我们深入解析与Android开发相关的知识体系,特别是针对Mars Android视频教程,这是一套旨在帮助开发者提升技能、掌握最新技术动态的宝贵资源。以下是对标题、描述以及相关内容...
2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。...
### 移动安全-APP渗透进阶之AppCan本地文件解密 #### 一、概述 随着移动应用的快速发展,应用程序的安全性变得越来越重要。在本文档中,我们将深入探讨如何对采用AppCan混合开发技术的应用进行渗透测试,并重点...
【Cocos2D-X 跨平台游戏开发环境搭建详解(Win32)】 Cocos2D-X 是一个广泛使用的...随着对Cocos2D-X的深入学习,你会发现更多高级功能和优化技巧,助你实现更复杂的交互和视觉效果。祝你在游戏开发之旅中取得成功!
【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或...
Android是全球最受欢迎的移动操作系统之一,它为开发者提供了丰富的平台来构建创新的移动应用程序。这份“Android资料学习大全”显然是一份全面的学习资源,旨在帮助初学者和有经验的开发者深入理解Android开发的...
### 辛星SQLite教程2016年Win版知识点概览 #### SQLite简介 - **背景**: 在数据库领域,人们通常会想到Oracle、DB2、MySQL等知名数据库系统。但有一种轻量级的数据库——SQLite,它以独特的嵌入式特性在众多应用...
CMake是一款跨平台的自动化构建系统,用于管理软件构建过程。它通过简洁的语法和配置文件(CMakeLists.txt)来描述项目结构和构建规则,然后生成针对不同编译器和构建工具的本地构建文件,如Visual Studio解决方案或...
对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同...
Maven是一款强大的项目管理工具,尤其在Java开发领域广泛应用。本教程将指导你如何使用Maven进行Android开发,包括配置、项目管理和资源管理。 **1. 安装必备软件与系统配置** 在开始之前,你需要确保系统已安装...
总的来说,"Hexagon.zip"是一个典型的Android Studio项目,适合初学者或经验丰富的开发者研究Android应用的开发流程和代码实现。通过分析这些文件,我们可以了解Android应用的基本结构,学习如何配置项目,以及如何...
"一加驱动包"是一个专为一加手机设计的驱动程序集合,旨在帮助用户解决与一加设备连接、数据同步、刷机等过程中可能出现的驱动问题。一加手机作为知名的智能手机品牌,其驱动程序对于保证手机正常运行和进行高级操作...
【标题】:“简单的图片浏览器”是一...综上所述,“简单的图片浏览器”不仅是一个实用的应用,也是一个学习安卓开发的好素材,涵盖了从基础到进阶的诸多知识点。无论是对于初学者还是经验丰富的开发者,都能从中获益。