2012年11月30日 星期五

Android:循環Gallery

public class MainActivity extends Activity {
private ImageAdapter imageAdapter=null;
private Gallery gallery=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gallery=(Gallery)findViewById(R.id.gallery1);
//設定Adapter
gallery.setAdapter(new ImageAdapter(this));
gallery.setGravity(Gravity.CENTER_HORIZONTAL);//效果目前不明     
gallery.setUnselectedAlpha(0.3f);//未選到的圖片比較暗                   
                gallery.setSpacing(20);//圖片與圖片間的間隔 
        
gallery.setOnItemSelectedListener(new OnItemSelectedListener() {

@Override
public void onItemSelected(AdapterView<?> adapterView, View view,
int position, long id) {
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
gallery.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
}
});
}


}

package com.briview.mgallery;

import ...

public class ImageAdapter extends BaseAdapter {
private Context context;
int imgArr[]={R.drawable.r0,R.drawable.r100,R.drawable.r150,R.drawable.r20};

public ImageAdapter(Context context){
this.context=context;
}
@Override
public int getCount() {
//修改返回值為無限大
return Integer.MAX_VALUE;
}

@Override
public Object getItem(int position) {
return imgArr[position];
}

@Override
public long getItemId(int position) {
return position;
}

@SuppressWarnings("deprecation")
@Override
public View getView(int position, View v, ViewGroup parent) {
//new a imageview to show pic
ImageView imageview=new ImageView(context);
//參數意義為讓使用者出圖片index範圍時,跳回第一張,Ex:5%4=1
imageview.setImageResource(imgArr[position%imgArr.length]);
//set the layout,determine how the pic to show
imageview.setLayoutParams(new Gallery.LayoutParams(480,800));
imageview.setScaleType(ImageView.ScaleType.CENTER);
imageview.setBackgroundColor(Color.alpha(1)); 
return imageview;
}


}



2012年11月29日 星期四

2012年11月27日 星期二

Android:Service啟動方式,BindService


  1. 建立class並extends android.app.Service, override其需要的method
  2. public IBinder onBind(Intent intent) 需要回傳一個IBinder物件, 在實作上我們回傳一個extends Binder類別的物件, EX: LocalBinder
  3. 在這個LocalBinder類別中, 我們定義一個method, 讓它可以取得一個Service物件, 這也是使用Binder Service最主要的目的
  4. 我們可以將想再背景執行Service的程式碼寫在一個自訂的方法中, 以供之後從Activity呼叫
  5. 在main activity中, 使用ServiceConnection物件類別來進行與Service連線, 並實作需要的method, 在public void onServiceConnected(ComponentName name, IBinder service)中, 使用參數傳進來的service轉型成自定義的LocalBinder後, 呼叫自行定義的方法, 取得Service
  6. 接著在使用Intent物件,設定好main activity以及Service,再來就可以啟動服務啦 bindService(intent, mServConn, BIND_AUTO_CREATE);
  7. 記得不需要服務後,要將Service 連線給Unbind   unbindService(mServConn);
先註冊Service至manifest.xml中


package com.servicedemo;

import ...

public class MyService extends Service {
private LocalBinder myBinder=new LocalBinder();
private MyService myService;
@Override
public IBinder onBind(Intent intent) {
Log.d("MyService", "onBind");
return myBinder;
}

@Override
public void onCreate() {
Log.d("MyService", "onCreate");
super.onCreate();
}

@Override
public void onDestroy() {
Log.d("MyService", "onDestroy");
super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}

@Override
public boolean onUnbind(Intent intent) {
Log.d("MyService", "onUnBind");
return super.onUnbind(intent);
}
//Service自行提供可供操作的方法
public void doSomeThing(TextView textView){
textView.setText("Service提供的方法...");
}
/*
* inner class extends Binder
*/
public class LocalBinder extends Binder{
MyService getService(){
return MyService.this;
}
}

}



package com.servicedemo;

import...
import com.servicedemo.MyService.LocalBinder;

public class Main extends Activity {
private TextView textView;
private MyService mService = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView1);
}
public void bindService_onClick(View v) {
mService = null;
Intent intent = new Intent(Main.this, MyService.class);
this.bindService(intent, mServConn, BIND_AUTO_CREATE);
}

public void unBindService_onClick(View v) {
mService = null;
this.unbindService(mServConn);
}

public void callServiceMethod_onClick(View v) {
if (mService != null)
mService.doSomeThing(textView);
}
/*
* 目的:為了取得Service物件,進而操作其public的方法
* 作法:在這function會接收到由service內的onBinde()所丟出來的Ibinder物件
* 利用這IBinder物件取得Service物件,就可以直接操作Service內各個public 的method
*/
private ServiceConnection mServConn = new ServiceConnection() {
// bind Service過程中,系統會呼叫執行以下程式碼
@Override
public void onServiceConnected(ComponentName name, IBinder service) {

mService = ((LocalBinder) service).getService();
}

// Service發生意外才會執行
@Override
public void onServiceDisconnected(ComponentName name) {

}

};

}




2012年11月26日 星期一

Android: View Bitmap Canvas與Drawable


View:Android顯示畫面的容器,可以是內建任何繼承View的元件,像是ImageView GridView Button等,也可以是自建繼承View的類別

 Bitmap:可視為儲存圖片畫素內容的物件,它可以將許多不同格式的圖片轉換成串流(0與1)讓系統可以看得懂

 Canvas:可視為畫布或是小畫家工具,你可以在上面話一條線,一個圓或是任何東西,畫完之後再將他奘到容器裡顯示,通常是在自建的View中顯示,然後當程式執行時便會呼叫這個新類別的onDraw()方法自動繪製

 Drawable:Android提供了許多不同框架的Drawable物件可供使用,像BitmapDrawable, ScaleDrawable, ShapeDrawable等等等...使用方法通常是直接將Drawable直接設定給容器即可(像是ImageView)

Android: Reflection效果



 View:Android顯示畫面的容器,可以是內建任何繼承View的元件,像是ImageView GridView Button等,也可以是自建繼承View的類別

 Bitmap:可視為儲存圖片畫素內容的物件,它可以將許多不同格式的圖片轉換成串流(0與1)讓系統可以看得懂

 Canvas:可視為畫布或是小畫家工具,你可以在上面話一條線,一個圓或是任何東西,畫完之後再將他奘到容器裡顯示,通常是在自建的View中顯示,然後當程式執行時便會呼叫這個新類別的onDraw(Canvas canvas)方法自動繪製

 Drawable:Android提供了許多不同框架的Drawable物件可供使用,像BitmapDrawable, ScaleDrawable, ShapeDrawable等等等...使用方法通常是直接將Drawable直接設定給容器即可(像是ImageView)
  
 

這個例子特別的點是在, 通常我們為了達到彈性需求(不想用內建的容器像ImageView、GridView、ListView、Button、EditText...
所以會是利用一個類別繼承View來當成容器,然後利用Canvas畫完之後,再將他裝到自建的容器中顯示,通常的做法是在@override中的onDraw(Canvas canvas)中,這個參數傳進來的canvas可視為一張撲滿螢幕的大畫布利用各式的Drawable物件將Canvas給畫出




package com.briview.reflection;

import ...
public class MainActivity extends Activity {
private ImageView imageView;

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

imageView = (ImageView) findViewById(R.id.imageView1);
Bitmap bmp = ((BitmapDrawable) getResources().getDrawable(R.drawable.a))
.getBitmap();
imageView.setImageBitmap(createReflectedImage(bmp));

}

/*
* public static Bitmap createBitmap (Bitmap source, int x, int y, int
* width, int height, Matrix m, boolean filter) 須注意以下規則 x + width <=
* bmp.getWidth(); y + height <= bmp.getHeight();
*/

private Bitmap createReflectedImage(Bitmap originalImage) {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
/*
* create bitmap object
*/
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
// 創建總圖片(原圖片 + 倒影圖片)
Bitmap finalReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
Paint shaderPaint = new Paint();
// 創建線性漸變LinearGradient物件
LinearGradient shader = new LinearGradient(0,
originalImage.getHeight(), 0, finalReflection.getHeight() + 1,
0x70ffffff, 0x00ffffff, TileMode.MIRROR);
shaderPaint.setShader(shader);
// 漸層效果!!
shaderPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// 畫布畫出反轉圖片大小區域,然後把漸變效果加到其中,就出現了圖片的倒    
                   影效果。


/*
 * draw on the canvas
 */
// 創建畫布
Canvas canvas = new Canvas(finalReflection);
canvas.drawBitmap(originalImage, 0, 0, null);
canvas.drawBitmap(reflectionImage, 0, height + 1, null);


canvas.drawRect(0, height + 1, width, finalReflection.getHeight(),
           shaderPaint);

return finalReflection;

}

}



2012年11月21日 星期三

Android:[轉]OpenGL 投影方式

Ref: http://fansofjava.iteye.com/blog/1499991

关于android的投影矩阵,一般有两种,一种是矩阵投影,另一种是透视投影。 
矩阵投影主要用于2D画面,但指定此投影的方式却有多种方式,而且对于初入门的人来说,也不容易理解,可以使用glOrthof,此方法使用方式大概如下: 
Java代码  收藏代码
  1. GL10 gl = glGraphics.getGL();  
  2. gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());  
  3. gl.glMatrixMode(GL10.GL_PROJECTION);  
  4. gl.glLoadIdentity();  
  5.   
  6. //以左下角为原点  
  7. gl.glOrthof(0, //left  
  8.             width,  //right  
  9.             0, //bottom  
  10.             height, //top  
  11.             1, -1);  
  12. gl.glMatrixMode(GL10.GL_MODELVIEW);  
  13. gl.glLoadIdentity();  

上面的glOrthof最后两个参数用于设置Z轴坐标,在2D画面中使用1与-1即可。 

除了这种方式外,还可以通过一个叫GLU的工具类来指定投影的显示,用法如下: 
Java代码  收藏代码
  1. gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());  
  2. gl.glMatrixMode(GL10.GL_PROJECTION);  
  3. gl.glLoadIdentity();  
  4. GLU.gluOrtho2D(gl, left, right, bottom, top);  
  5. gl.glMatrixMode(GL10.GL_MODELVIEW);  
  6. gl.glLoadIdentity();  

上面的gluOrtho2D方法相对来说简化了一下。 

在3D的画面中,也有两种方式,一种是使用glFrustumf方法,用法如下: 
Java代码  收藏代码
  1.        gl.glViewport(0, 0, width, height);  
  2. float ratio = (float) width / height;  
  3. gl.glMatrixMode(GL10.GL_PROJECTION);  
  4. gl.glLoadIdentity();  
  5. gl.glFrustumf(-ratio, ratio, -1, 1, 1, 20);  

这个ratio表示宽度与高度的比,glFrustumf方法的前两个参数分别代表左右方向,因为高度与宽度不一样,所以这个ratio是为了限制场景宽度而必须存在的。第三四个参数分别代表Y的下上方向,而最后两个参数则代表Z轴的近远方向。这个近与远不是很好理解的话请看下图: 

 
上面这个图也把Viewport与场景区分开了。 

除了使用glFrustumf外,也可以使用工具类GLU里面的方法gluPerspective,此方法参数如下: 
Java代码  收藏代码
  1. GLU.gluPerspective(gl, fovy, aspect, zNear, zFar);  

其中第二个参数表示角度,即视图的角度。而aspect则表示宽度与高度比,即与上面的ratio一样。但这些参数最好还是配上一个图,下面的图来自最后链接文章,个人觉得很形象的说明了这些参数的意思。 
 

引用

我们观察平面的裁剪窗口的大小和屏幕的大小可以一致,也可以有差别. 但为了使得最终的效果基本一致,所以,一般设置成它们具有相同的 aspect(横纵比 w/h), 从而它们的转换关系就是等比例的放大或者缩小,而不会产生扭曲. 

对于3D图形来说,除了设置视图投影以外,还得设置整个游戏模型的浏览角度,这个会涉及到一个很重要的方法GLU.gluLookAt,这个方法的参数形式如下: 
Java代码  收藏代码
  1. void android.opengl.GLU.gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)  

参数很多,但参数作用主要分为三部分(gl不算)。 
eye系列坐标用于设置整个视野所参照的原点坐标。 
center系列坐标用于设置浏览游戏角色的方向,这个方向坐标就是相对于eye系统坐标的。 
up系列坐标则用于设置浏览者(镜头)相对于原点(eye系列)的坐标。 
下图可供参考: 
 
因此在3D环境中,整个游戏的视图设置大概就像下面这样,先设置投影矩阵下整个游戏的面板的显示,再设置为模型矩阵,显示3D模型的轮廓: 
Java代码  收藏代码
  1. public void setMatrices(GL10 gl) {  
  2.   gl.glMatrixMode(GL10.GL_PROJECTION);  
  3.   gl.glLoadIdentity();  
  4.   GLU.gluPerspective(gl, fieldOfView, aspectRatio, near, far);  
  5.   gl.glMatrixMode(GL10.GL_MODELVIEW);  
  6.   gl.glLoadIdentity();  
  7.   GLU.gluLookAt(gl, position.x, position.y, position.z, lookAt.x, lookAt.y, lookAt.z, up.x, up.y, up.z);  
  8. }  

Eclipse:Android專案匯入問題 gen already exists but is not a source folder. Convert to a source folder or rename it"


Try this, it helped me:
  1. Right click on the project and go to "Properties"
  2. Select "Java Build Path" on the left
  3. Open "Source" tab
  4. Click "Add Folder..."
  5. Check "gen" folder and click Ok and Ok again
  6. Again right click on the project and in the "Andriod Tools" click on "Fix Project Properties"