Never Nop Tech

Never Nop Tech

創造意義,動手去做。

[Android] Camera拍照預覽圖片90度旋轉

Camera拍照:

做觀景窗程式,結果寫好了發現出問題了,預覽的圖像差90度。相關原始程式碼如下:

Camera.Parameters params = camera.getParameters();
params.setPreviewSize(width, height);
params.setPreviewFrameRate(4);
params.setPictureFormat(PixelFormat.JPEG);
params.set(“jpeg-quality", 85);
params.setPictureSize(width, height);
camera.setParameters(params);
camera.setPreviewDisplay(sHolder);
camera.startPreview();
camera.autoFocus(null);

於是在網上搜索,發現確實存在這樣一個問題,網上的解決方法也各不一致。最後用setDisplayOrientation()方法解決了,修改後的代碼如下:

Camera.Parameters params = camera.getParameters();
params.setPreviewSize(height, width); 1
params.setPreviewFrameRate(4);
params.setPictureFormat(PixelFormat.JPEG);
params.set(“jpeg-quality", 85);
params.setPictureSize(height, width); 2
camera.setParameters(params);
camera.setDisplayOrientation(90); 3
camera.setPreviewDisplay(sHolder);
camera.startPreview();
camera.autoFocus(null);

首先添加了代碼3,讓Camera旋轉90度。測試時發現雖然圖像轉回正常,但是上下卻拉長了。進過研究修改代碼1,把長寬顛倒。再測試預覽正常了,但是拍照的時候獲取的圖片卻依然是拉長的,於是修改代碼2。這回拍照正常,但是仍然存在一個問題,保存的圖片是橫著的。

看網上很多人都遇到了這個問題,好像與系統有關,既然沒法在Camera這裡搞定,那麼就將獲取的Bitmap進行旋轉。程式裡通過重寫PictureCallback的onPictureTaken來獲取圖片,代碼是

Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);

在這裡可以對bm進行旋轉,代碼如下:

Bitmap bm0 = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix m = new Matrix();
m.setRotate(90,(float) bm0.getWidth() / 2, (float) bm0.getHeight() / 2);
final Bitmap bm = Bitmap.createBitmap(bm0, 0, 0, bm0.getWidth(), bm0.getHeight(), m, true);

這樣保存的圖片就正常了!

 

MediaRecorder錄影:

同樣的預覽問題在錄影中也出現了,但是由於是用MediaRecorder進行錄影,沒有Camera物件,一時比較無措。後來經過網友的提醒,想到了MediaRecorder有setCamera()的方法,於是添加如下代碼:

Camera c = Camera.open();
c.setDisplayOrientation(90);
c.unlock();
mRecorder.setCamera(c);

這樣預覽的問題就解決了!至於網上很多人說添加mRecorder.setOrientationHint(90); 這個方法並不能改變預覽的角度,這個方法會改變保存後的視頻檔播放時是否是橫向。根據使用者的習慣,最後也添加這個代碼保證在播放視頻是是橫向的。

來自:HTTP://blog.sina.com.cn/s/blog_49e44eb001018p69.html

[Android] 從Camera中獲取圖片的兩種方法

方法一:

方法會由Camera直接產生照片回傳給應用程式,但是返回的是壓縮圖片,顯示不清晰

try {

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_WITH_DATA);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}

 

Bundle bundle = data.getExtras();
bmp_selectedPhoto = (Bitmap) bundle.get(“data");
if (bmp_selectedPhoto != null)
bmp_selectedPhoto.recycle();
bmp_selectedPhoto = (Bitmap) data.getExtras().get(“data");
int scale = ImageThumbnail.reckonThumbnail(bitMap.getWidth(),
bitMap.getHeight(), 500, 600);
bitMap = ImageThumbnail.PicZoom(bitMap,
(int) (bitMap.getWidth() / scale),
(int) (bitMap.getHeight() / scale));
bitMap = ThumbnailUtils.extractThumbnail(bitMap, 200, 200);
if(bmp_selectedPhoto != null){
home_view.setBackground(new BitmapDrawable(getResources(),
bmp_selectedPhoto));
}

 

方法二:

此方法所拍即所得,但是會在Sd卡上產生暫存檔案
Intent cameraIntent = new Intent(

android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

File appDir = new File(Environment.getExternalStorageDirectory()

+ “/KengDieA");

 

if (!appDir.exists()) {
appDir.mkdir();
}

mUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory()

+ “/KengDieA/", “kengDiePic"
+ String.valueOf(System.currentTimeMillis()) + “.jpg"));
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mUri);

 

try {
cameraIntent.putExtra(“return-data", true);
startActivityForResult(cameraIntent, CAMERA_WITH_DATA);
} catch (Exception e) {
e.printStackTrace();
}

 

ContentResolver cr = this.getContentResolver();
try {
if (bmp_selectedPhoto != null)// 如果不釋放的話,不斷取圖片,將會記憶體不夠
bmp_selectedPhoto.recycle();
bmp_selectedPhoto = BitmapFactory.decodeStream(cr
.openInputStream(mUri));
} catch (FileNotFoundException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
home_view.setBackground(new BitmapDrawable(getResources(),
bmp_selectedPhoto));

[Android] camera拍攝surfaceview預覽介面特定區域

1.自定义一个imageview用来设定surfaceview上的特定区域。

 

public class DrawImageView extends ImageView {
private Paint paint;
private int mFristPointX = 100, mFristPointY = 200;
private int mSecondPointX = 400, mSecondPointY = 500;
private boolean isFirstDown = true;

private int mOldX = 0, mOldY = 0;

public DrawImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}

public DrawImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}

private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2.5f);
paint.setAlpha(100);
}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawRect(new Rect(getmFristPointX(), getmFristPointY(), getmSecondPointX(), getmSecondPointY()), paint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() != MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
Rect mRect = new Rect(getmFristPointX(), getmFristPointY(), getmSecondPointX(), getmSecondPointY());
if (mRect.contains(x, y)) {
if (isFirstDown) {
mOldX = x;
mOldY = y;
isFirstDown = false;
} else {
int mXDis = x – mOldX;
int mYDis = y – mOldY;
mOldX = x;
mOldY = y;
ReSetVaue(mXDis, mYDis);
}
}
} else {
isFirstDown = true;
}
return true;
}

public void setValue(int x, int y) {
setmFristPointX(x – 50);
setmFristPointY(y – 50);
setmSecondPointX(x + 50);
setmSecondPointY(y + 50);
invalidate();
}

public void ReSetVaue(int xDis, int yDis) {
setmFristPointX(getmFristPointX() + xDis);
setmFristPointY(getmFristPointY() + yDis);
setmSecondPointX(getmFristPointX() + 100);
setmSecondPointY(getmFristPointY() + 100);
invalidate();
}

public int getmFristPointX() {
return mFristPointX;
}

public void setmFristPointX(int mFristPointX) {
this.mFristPointX = mFristPointX;
}

public int getmFristPointY() {
return mFristPointY;
}

public void setmFristPointY(int mFristPointY) {
this.mFristPointY = mFristPointY;
}

public int getmSecondPointX() {
return mSecondPointX;
}

public void setmSecondPointX(int mSecondPointX) {
this.mSecondPointX = mSecondPointX;
}

public int getmSecondPointY() {
return mSecondPointY;
}

public void setmSecondPointY(int mSeconPointY) {
this.mSecondPointY = mSeconPointY;
}

}
2.定义xml布局。

 

 

<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1″ >

<SurfaceView
android:id="@+id/open_camera"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="15dp" />

<test.camera.cut.DrawImageView
android:id="@+id/draw_rect"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="15dp" />
</FrameLayout>
3.在surfaceChanged中设置参数开始画区域:

 

 

DrawImageView.onDraw(new Canvas());
DrawImageView.setValue(mFirstPointX, mFirstPointY);//左上角点的值
4.在camera拍照部分进行压缩裁剪。

private Bitmap mBitmap;

private Camera.PictureCallback takePictureCallback = new Camera.PictureCallback() {

@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub

if (data != null) {
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
camera.stopPreview();
}
Matrix matrix = new Matrix();
matrix.setRotate(90);
Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);

getSurfaceSize();
Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, SurView_Width, SurView_Height, true);
SaveBitmap(sizeBitmap);
mFirstPointX = mDrawImageView.getmFristPointX() + 50;
mFirstPointY = mDrawImageView.getmFristPointY() + 50;

Bitmap newBitmap = Bitmap.createBitmap(sizeBitmap, mFirstPointX – 50, mFirstPointY – 50, 100, 100);

if (newBitmap != null) {
mTestImageView.setImageBitmap(newBitmap);
}

camera.startPreview();

}
};

private void getSurfaceSize(){
SurView_Width = mSurfaceView.getWidth();
SurView_Height = mSurfaceView.getHeight();
}

private void SaveBitmap(Bitmap bitmap) {
File mpicture = new File(mPath + File.separator + “pic.jpg");
try {
mpicture.createNewFile();
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(mpicture));
bitmap.compress(CompressFormat.JPEG, 75, outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

 

参考文献: http://blog.csdn.net/yanzi1225627/article/details/8580034

[Android] camera preview方向

在surfacechange中執行:

int mDisplayRotation = 0;
int mDisplayOrientation = getWindowManager().getDefaultDisplay().getRotation() * 90;
CameraInfo mCameraInfo = new CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, mCameraInfo);
int mCameraOrientation = mCameraInfo.orientation;
if (mCameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
mDisplayRotation = (mCameraOrientation – mDisplayOrientation + 360) % 360;
} else {
mDisplayRotation = (mCameraOrientation + mDisplayOrientation) % 360;
mDisplayRotation = (360 – mDisplayRotation) % 360;
}
mCamera.setDisplayOrientation(mDisplayRotation);

[Android] 拍照旋轉圖片

public class ImageUtil {

public static final String TAG = ImageUtil.class.getSimpleName();

/**
* 判斷圖片是否需要翻轉(正方向的不用翻轉)
*
* @param fileName
* @return
*/
public static boolean needRotate(CoNtext coNtext, String fileName) {
try {
ExifInterface exif = new ExifInterface(fileName);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
LogUtil.d(TAG, “orientation is " + orientation);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return true;
case ExifInterface.ORIENTATION_ROTATE_270:
return true;
case ExifInterface.ORIENTATION_ROTATE_180:
return true;
}

return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}

/**
* 獲取翻轉到正方向的的圖片
*
* @param fileName
* @param maxWidth
* @param maxHeight
* @return
*/
public static void rotatedBitmap(CoNtext coNtext, String fileName,
String dstFile) {
try {
ExifInterface exif = new ExifInterface(fileName);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
LogUtil.d(TAG, “orientation is " + orientation);
Matrix matrix = null;

switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix = new Matrix();
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix = new Matrix();
matrix.postRotate(270);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix = new Matrix();
matrix.postRotate(180);
break;
}

Bitmap bmp = getSmallBitmap(coNtext,
Uri.fromFile(new File(fileName)));
if (matrix != null) {
Bitmap bmp2 = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
bmp.getHeight(), matrix, true);
bmp.recycle();

FileOutputStream fos = new FileOutputStream(dstFile);
bmp2.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
bmp2.recycle();
}
} catch (IOException e) {
e.printStackTrace();
}
}

public static boolean compress(CoNtext coNtext, Uri src, File dst, int rate) {
try {
Bitmap bmp = getSmallBitmap(coNtext, src);
FileOutputStream fos = new FileOutputStream(dst);
bmp.compress(Bitmap.CompressFormat.JPEG, rate, fos);
bmp.recycle();
bmp = null;
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}

public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {

final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;

}

public static Bitmap getSmallBitmap(CoNtext coNtext, Uri uri) {
try {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream is = coNtext.getContentResolver().openInputStream(uri);
BitmapFactory.decodeStream(is, null, options);
is.close();

Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 720, 1280);

Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;

is = coNtext.getContentResolver().openInputStream(uri);
Bitmap bmp = BitmapFactory.decodeStream(is, null, options);
is.close();
return bmp;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

[Android] 打開前置攝像頭和後置攝像頭

前言:
我 的android設備是原道N70雙擎pad。 這個平板電腦沒有後置攝像頭,只有前置攝像頭,當我安裝一些程式的時候,會出現「xxxx.apk已經終止」的錯誤,然後程式就會退出。 思前想後,發現一般的應用程式是安裝在手機上的,程式的預設攝像頭是後置攝像頭。 由於我的pad沒有後置攝像頭,所以,調用後置攝像頭就發生失敗! 怎麼解決呢?
解決問題
程式設計的時候,我們在調用Camera函數的open函數之前,必須查找是否有可用的攝像頭。 然後將查找到的攝像頭序號傳遞給Camera類的open函數。

 

@TargetApi(9)
private int FindFrontCamera(){
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); get cameras number

 

for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) {
Camera.getCameraInfo( camIdx, cameraInfo ); get camerainfo
if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_FRONT ) {
代表攝像頭的方位,目前有定義值兩個分別為CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK後置
return camIdx;
}
}
return -1;
}
@TargetApi(9)
private int FindBackCamera(){
int cameraCount = 0;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras(); get cameras number

 

for ( int camIdx = 0; camIdx < cameraCount;camIdx++ ) {
Camera.getCameraInfo( camIdx, cameraInfo ); get camerainfo
if ( cameraInfo.facing ==Camera.CameraInfo.CAMERA_FACING_BACK ) {
代表攝像頭的方位,目前有定義值兩個分別為CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK後置
return camIdx;
}
}
return -1;
}
public void surfaceCreated(SurfaceHolder holder) {
int CammeraIndex=FindBackCamera();
if(CammeraIndex==-1){
CammeraIndex=FindFrontCamera();
}
mCamera = Camera.open(CammeraIndex);
}

孫子兵法翻譯本

常歡迎您光臨「 孫子兵法翻譯本」(以下簡稱本應用程式),為了讓您能夠安心的使用本應用程式的各項服務與資訊,特此向您說明本應用程式的隱私權保護政策,以保障您的權益,請您詳閱下列內容:

一、隱私權保護政策的適用範圍

隱私權保護政策內容,包括本應用程式如何處理在您使用應用程式服務時收集到的個人識別資料。隱私權保護政策不適用於本應用程式以外的相關連結應用程式,也不適用於非本應用程式所委託或參與管理的人員。

二、個人資料的蒐集、處理及利用方式

  • 當您造訪本應用程式或使用本應用程式所提供之功能服務時,我們將視該服務功能性質,請您提供必要的個人資料,並在該特定目的範圍內處理及利用您的個人資料;非經您書面同意,本應用程式不會將個人資料用於其他用途。
  • 本應用程式在您使用服務信箱、問卷調查等互動性功能時,會保留您所提供的姓名、電子郵件地址、聯絡方式及使用時間等。
  • 於一般瀏覽時,伺服器會自行記錄相關行徑,包括您使用連線設備的IP位址、使用時間、使用的瀏覽器、瀏覽及點選資料記錄等,做為我們增進應用程式服務的參考依據,此記錄為內部應用,決不對外公佈。
  • 為提供精確的服務,我們會將收集的問卷調查內容進行統計與分析,分析結果之統計數據或說明文字呈現,除供內部研究外,我們會視需要公佈統計數據及說明文字,但不涉及特定個人之資料。

三、資料之保護

  • 本應用程式主機均設有防火牆、防毒系統等相關的各項資訊安全設備及必要的安全防護措施,加以保護應用程式及您的個人資料採用嚴格的保護措施,只由經過授權的人員才能接觸您的個人資料,相關處理人員皆簽有保密合約,如有違反保密義務者,將會受到相關的法律處分。
  • 如因業務需要有必要委託其他單位提供服務時,本應用程式亦會嚴格要求其遵守保密義務,並且採取必要檢查程序以確定其將確實遵守。

四、應用程式對外的相關連結

本應用程式的網頁提供其他應用程式的網路連結,您也可經由本應用程式所提供的連結,點選進入其他應用程式。但該連結應用程式不適用本應用程式的隱私權保護政策,您必須參考該連結應用程式中的隱私權保護政策。

五、與第三人共用個人資料之政策

本應用程式絕不會提供、交換、出租或出售任何您的個人資料給其他個人、團體、私人企業或公務機關,但有法律依據或合約義務者,不在此限。

前項但書之情形包括不限於:

  • 經由您書面同意。
  • 法律明文規定。
  • 為免除您生命、身體、自由或財產上之危險。
  • 與公務機關或學術研究機構合作,基於公共利益為統計或學術研究而有必要,且資料經過提供者處理或蒐集者依其揭露方式無從識別特定之當事人。
  • 當您在應用程式的行為,違反服務條款或可能損害或妨礙應用程式與其他使用者權益或導致任何人遭受損害時,經應用程式管理單位研析揭露您的個人資料是為了辨識、聯絡或採取法律行動所必要者。
  • 有利於您的權益。
  • 本應用程式委託廠商協助蒐集、處理或利用您的個人資料時,將對委外廠商或個人善盡監督管理之責。

六、Cookie 之使用

為了提供您最佳的服務,本應用程式會在您的電腦中放置並取用我們的Cookie,若您不願接受Cookie的寫入,您可在您使用的瀏覽器功能項中設定隱私權等級為高,即可拒絕Cookie的寫入,但可能會導至應用程式某些功能無法正常執行 。

七、隱私權保護政策之修正

本應用程式隱私權保護政策將因應需求隨時進行修正,修正後的條款將刊登於應用程式上。

孔子語錄翻譯本 隱私政策

常歡迎您光臨「 孔子語錄翻譯本」(以下簡稱本應用程式),為了讓您能夠安心的使用本應用程式的各項服務與資訊,特此向您說明本應用程式的隱私權保護政策,以保障您的權益,請您詳閱下列內容:

一、隱私權保護政策的適用範圍

隱私權保護政策內容,包括本應用程式如何處理在您使用應用程式服務時收集到的個人識別資料。隱私權保護政策不適用於本應用程式以外的相關連結應用程式,也不適用於非本應用程式所委託或參與管理的人員。

二、個人資料的蒐集、處理及利用方式

  • 當您造訪本應用程式或使用本應用程式所提供之功能服務時,我們將視該服務功能性質,請您提供必要的個人資料,並在該特定目的範圍內處理及利用您的個人資料;非經您書面同意,本應用程式不會將個人資料用於其他用途。
  • 本應用程式在您使用服務信箱、問卷調查等互動性功能時,會保留您所提供的姓名、電子郵件地址、聯絡方式及使用時間等。
  • 於一般瀏覽時,伺服器會自行記錄相關行徑,包括您使用連線設備的IP位址、使用時間、使用的瀏覽器、瀏覽及點選資料記錄等,做為我們增進應用程式服務的參考依據,此記錄為內部應用,決不對外公佈。
  • 為提供精確的服務,我們會將收集的問卷調查內容進行統計與分析,分析結果之統計數據或說明文字呈現,除供內部研究外,我們會視需要公佈統計數據及說明文字,但不涉及特定個人之資料。

三、資料之保護

  • 本應用程式主機均設有防火牆、防毒系統等相關的各項資訊安全設備及必要的安全防護措施,加以保護應用程式及您的個人資料採用嚴格的保護措施,只由經過授權的人員才能接觸您的個人資料,相關處理人員皆簽有保密合約,如有違反保密義務者,將會受到相關的法律處分。
  • 如因業務需要有必要委託其他單位提供服務時,本應用程式亦會嚴格要求其遵守保密義務,並且採取必要檢查程序以確定其將確實遵守。

四、應用程式對外的相關連結

本應用程式的網頁提供其他應用程式的網路連結,您也可經由本應用程式所提供的連結,點選進入其他應用程式。但該連結應用程式不適用本應用程式的隱私權保護政策,您必須參考該連結應用程式中的隱私權保護政策。

五、與第三人共用個人資料之政策

本應用程式絕不會提供、交換、出租或出售任何您的個人資料給其他個人、團體、私人企業或公務機關,但有法律依據或合約義務者,不在此限。

前項但書之情形包括不限於:

  • 經由您書面同意。
  • 法律明文規定。
  • 為免除您生命、身體、自由或財產上之危險。
  • 與公務機關或學術研究機構合作,基於公共利益為統計或學術研究而有必要,且資料經過提供者處理或蒐集者依其揭露方式無從識別特定之當事人。
  • 當您在應用程式的行為,違反服務條款或可能損害或妨礙應用程式與其他使用者權益或導致任何人遭受損害時,經應用程式管理單位研析揭露您的個人資料是為了辨識、聯絡或採取法律行動所必要者。
  • 有利於您的權益。
  • 本應用程式委託廠商協助蒐集、處理或利用您的個人資料時,將對委外廠商或個人善盡監督管理之責。

六、Cookie 之使用

為了提供您最佳的服務,本應用程式會在您的電腦中放置並取用我們的Cookie,若您不願接受Cookie的寫入,您可在您使用的瀏覽器功能項中設定隱私權等級為高,即可拒絕Cookie的寫入,但可能會導至應用程式某些功能無法正常執行 。

七、隱私權保護政策之修正

本應用程式隱私權保護政策將因應需求隨時進行修正,修正後的條款將刊登於應用程式上。

經典語錄隱私政策

常歡迎您光臨「經典語錄」(以下簡稱本應用程式),為了讓您能夠安心的使用本應用程式的各項服務與資訊,特此向您說明本應用程式的隱私權保護政策,以保障您的權益,請您詳閱下列內容:

一、隱私權保護政策的適用範圍

隱私權保護政策內容,包括本應用程式如何處理在您使用應用程式服務時收集到的個人識別資料。隱私權保護政策不適用於本應用程式以外的相關連結應用程式,也不適用於非本應用程式所委託或參與管理的人員。

二、個人資料的蒐集、處理及利用方式

  • 當您造訪本應用程式或使用本應用程式所提供之功能服務時,我們將視該服務功能性質,請您提供必要的個人資料,並在該特定目的範圍內處理及利用您的個人資料;非經您書面同意,本應用程式不會將個人資料用於其他用途。
  • 本應用程式在您使用服務信箱、問卷調查等互動性功能時,會保留您所提供的姓名、電子郵件地址、聯絡方式及使用時間等。
  • 於一般瀏覽時,伺服器會自行記錄相關行徑,包括您使用連線設備的IP位址、使用時間、使用的瀏覽器、瀏覽及點選資料記錄等,做為我們增進應用程式服務的參考依據,此記錄為內部應用,決不對外公佈。
  • 為提供精確的服務,我們會將收集的問卷調查內容進行統計與分析,分析結果之統計數據或說明文字呈現,除供內部研究外,我們會視需要公佈統計數據及說明文字,但不涉及特定個人之資料。

三、資料之保護

  • 本應用程式主機均設有防火牆、防毒系統等相關的各項資訊安全設備及必要的安全防護措施,加以保護應用程式及您的個人資料採用嚴格的保護措施,只由經過授權的人員才能接觸您的個人資料,相關處理人員皆簽有保密合約,如有違反保密義務者,將會受到相關的法律處分。
  • 如因業務需要有必要委託其他單位提供服務時,本應用程式亦會嚴格要求其遵守保密義務,並且採取必要檢查程序以確定其將確實遵守。

四、應用程式對外的相關連結

本應用程式的網頁提供其他應用程式的網路連結,您也可經由本應用程式所提供的連結,點選進入其他應用程式。但該連結應用程式不適用本應用程式的隱私權保護政策,您必須參考該連結應用程式中的隱私權保護政策。

五、與第三人共用個人資料之政策

本應用程式絕不會提供、交換、出租或出售任何您的個人資料給其他個人、團體、私人企業或公務機關,但有法律依據或合約義務者,不在此限。

前項但書之情形包括不限於:

  • 經由您書面同意。
  • 法律明文規定。
  • 為免除您生命、身體、自由或財產上之危險。
  • 與公務機關或學術研究機構合作,基於公共利益為統計或學術研究而有必要,且資料經過提供者處理或蒐集者依其揭露方式無從識別特定之當事人。
  • 當您在應用程式的行為,違反服務條款或可能損害或妨礙應用程式與其他使用者權益或導致任何人遭受損害時,經應用程式管理單位研析揭露您的個人資料是為了辨識、聯絡或採取法律行動所必要者。
  • 有利於您的權益。
  • 本應用程式委託廠商協助蒐集、處理或利用您的個人資料時,將對委外廠商或個人善盡監督管理之責。

六、Cookie 之使用

為了提供您最佳的服務,本應用程式會在您的電腦中放置並取用我們的Cookie,若您不願接受Cookie的寫入,您可在您使用的瀏覽器功能項中設定隱私權等級為高,即可拒絕Cookie的寫入,但可能會導至應用程式某些功能無法正常執行 。

七、隱私權保護政策之修正

本應用程式隱私權保護政策將因應需求隨時進行修正,修正後的條款將刊登於應用程式上。

android 關於EditView 輸入問題

很多寫登錄介面的開發者都會遇到一個問題:那就是在登錄介面時,當你點擊輸入框時,下邊的按鈕有時會被輸入框擋住,這個不利於用戶的體驗,所以很多人希望軟鍵盤彈出時,也能把按鈕擠上去。很多開發者想要監聽鍵盤的狀態,這無疑是一個很麻煩的做法。

 

我們可以在AndroidManifest.xml的Activity設置屬性:android:windowSoftInputMode = “adjustResize" ,軟鍵盤彈出時,要對主視窗佈局重新進行佈局,並調用onSizeChanged方法,切記一點當我們設置為「adjustResize」時,我們的介面不要設置為全屏模式,否則設置了這個屬性也不會有什麼效果。而當我們設置android: windowSoftInputMode = “adjustPan"時,主視窗就不會調用onSizeChanged方法,介面的一部分就會被軟鍵盤覆蓋住,就不會被擠到軟鍵盤之上了。

 

我們通過一段代碼來測試一下,當我們設置了該屬性後,彈出輸入法時,系統做了什麼:

 

重寫Layout佈局:

public class ResizeLayout extends LinearLayout{

    private static int count = 0;

    public ResizeLayout(Context context, AttributeSet attrs) {

        super(context, attrs);

    }

    @Override

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);

        Log.e(“onSizeChanged “ + count++, “=>onResize called! w="+w + “,h="+h+“,oldw="+oldw+“,oldh="+oldh);

    }

    @Override

    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        super.onLayout(changed, l, t, r, b);

        Log.e(“onLayout “ + count++, “=>OnLayout called! l=" + l + “, t=" + t + “,r=" + r + “,b="+b);

    }

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        Log.e(“onMeasure “ + count++, “=>onMeasure called! widthMeasureSpec=" + widthMeasureSpec + “, heightMeasureSpec=" + heightMeasureSpec);

    }

 

02.

 

我們的佈局設置為:

<com.winuxxan.inputMethodTest.ResizeLayout

    xmlns:android=“http://schemas.android.com/apk/res/android"

    android:id=“@+id/root_layout"

    android:layout_width=“fill_parent"

    android:layout_height=“fill_parent"

    android:orientation=“vertical"

    >

    <EditText

        android:layout_width=“fill_parent"

        android:layout_height=“wrap_content"

    />

    <LinearLayout

            android:id=“@+id/bottom_layout"

            android:layout_width=“fill_parent"

            android:layout_height=“fill_parent"

            android:orientation=“vertical"

            android:gravity=“bottom">s

    <TextView

        android:layout_width=“fill_parent"

        android:layout_height=“wrap_content"

        android:text=“@string/hello"

        android:background=“#77777777″

      />

   </LinearLayout>

</com.winuxxan.inputMethodTest.ResizeLayout>

 

02.

 

AndroidManifest.xml的Activity設置屬性:android:windowSoftInputMode = “adjustResize"
運行程式,點擊文字方塊,查看調試資訊:
E/onMeasure 6(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742024
E/onMeasure 7(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742025
E/onSizeChanged 8(7960): =>onSizeChanged called! w=320,h=201,oldw=320,oldh=377
E/onLayout 9(7960): =>OnLayout called! l=0, t=0,r=320,b=201
從調試結果我們可以看出,當我們點擊文字方塊後,根佈局調用了onMeasure,onSizeChanged和onLayout。

 

windowSoftInputMode的值如果設置為adjustPan,那麼該Activity主視窗並不調整螢幕的大小以便留出軟鍵盤的空間。相反,當前視窗的內容將自動移動以便當前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內容的部分。這個通常是不期望比調整大小,因為用戶可能關閉軟鍵盤以便獲得與被覆蓋內容的交交互操作。
上面的例子中,我們將AndroidManifest.xml的屬性進行更改:android: windowSoftInputMode = “adjustPan"

 

重新運行,並點擊文字方塊,查看調試資訊:
E/onMeasure 6(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742200
E/onMeasure 7(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742201
E/onLayout 8(8378): =>OnLayout called! l=0, t=0,r=320,b=377
我們看到:系統也重新進行了measrue和layout,但是我們發現,layout過程中onSizeChanged並沒有調用,這說明輸入法彈出前後並沒有改變原有佈局的大小。

 

當然還有其他屬性可以設置:

 

“stateUnspecified"

 

軟鍵盤的狀態(是否它是隱藏或可見)沒有被指定。系統將選擇一個合適的狀態或依賴於主題的設置。

 

這個是為了軟件盤行為默認的設置。

 

“stateUnchanged"

 

軟鍵盤被保持無論它上次是什麼狀態,是否可見或隱藏,當主視窗出現在前面時。

 

“stateHidden"

 

當用戶選擇該Activity時,軟鍵盤被隱藏——也就是,當用戶確定導航到該Activity時,而不是返回到它由於離開另一個Activity。

 

“stateAlwaysHidden"

 

軟鍵盤總是被隱藏的,當該Activity主視窗獲取焦點時。

 

“stateVisible"

 

軟鍵盤是可見的,當那個是正常合適的時(當用戶導航到Activity主視窗時)。

 

“stateAlwaysVisible"

 

當用戶選擇這個Activity時,軟鍵盤是可見的——也就是,也就是,當用戶確定導航到該Activity時,而不是返回到它由於離開另一個Activity。

 

“adjustUnspecified"

 

它不被指定是否該Activity主視窗調整大小以便留出軟鍵盤的空間,或是否視窗上的內容得到螢幕上當前的焦點是可見的。系統將自動選擇這些模式中一種主要依賴於是否視窗的內容有任何佈局視圖能夠滾動他們的內容。如果有這樣的一個視圖,這個視窗將調整大小,這樣的假設可以使滾動視窗的內容在一個較小的區域中可見的。這個是主視窗默認的行為設置。

 

“adjustResize"

 

該Activity主視窗總是被調整螢幕的大小以便留出軟鍵盤的空間

 

“adjustPan"

 

該Activity主視窗並不調整螢幕的大小以便留出軟鍵盤的空間。相反,當前視窗的內容將自動移動以便當前焦點從不被鍵盤覆蓋和用戶能總是看到輸入內容的部分。這個通常是不期望比調整大小,因為用戶可能關閉軟鍵盤以便獲得與被覆蓋內容的交交互操作。

 

相應用過Android手機的朋友都知道,有時候在文字方塊中輸入文字後,操作按鈕被輸入法遮擋了,不得不關閉輸入法才可以繼續操作。

 

比如下面這個畫面:

0_12977530695Rjx

畫面佈局:

 

<?xml version=“1.0″ encoding=“utf-8″?>  

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android"

    android:id=“@+id/ll2″ android:orientation=“vertical"

    android:layout_width=“fill_parent" android:layout_height=“fill_parent">

    <CheckBox android:id=“@+id/widget57″ android:layout_width=“wrap_content"

        android:layout_height=“wrap_content" android:text=“@string/location"

        android:layout_gravity=“right">

    </CheckBox>

    <EditText android:id=“@+id/widget34″ android:layout_width=“fill_parent"

        android:layout_height=“fill_parent" android:layout_weight=“1″

        android:textColorHighlight=“#cccccc" android:hint=“你想說什麼?"

        android:gravity=“top" android:textSize=“18sp">

    </EditText>

    <Button android:id=“@+id/widget53″ android:layout_width=“100px"

            android:layout_height=“wrap_content" android:text=“@string/share"

            android:layout_gravity=“right"/>

</LinearLayout>

 

如果不做任何操作,那麼點擊文字方塊後的效果肯定是下圖:

0_1297754184ACsf

此時,【共用】按鈕被輸入法擋住了,必須關閉輸入法才可以操作了。

 

有的朋友會說,可以在佈局外面再加一個ScrollView,這樣的畫,UI佈局就和輸入法分離了,輸入法出現後,上面還可以滾動。

 

但是這樣的效果好嗎? 我們來看一下效果(佈局外加ScrollView的效果):

0_12977534212DU4

畫面佈局:

<?xml version=“1.0″ encoding=“utf-8″?>

<ScrollView xmlns:android=“http://schemas.android.com/apk/res/android"

android:layout_width=“fill_parent" android:layout_height=“fill_parent"

android:orientation=“vertical">

<LinearLayout

android:id=“@+id/ll2″ android:orientation=“vertical"

android:layout_width=“fill_parent" android:layout_height=“fill_parent">

<CheckBox android:id=“@+id/widget57″ android:layout_width=“wrap_content"

android:layout_height=“wrap_content" android:text=“@string/location"

android:layout_gravity=“right">

</CheckBox>

<EditText android:id=“@+id/widget34″ android:layout_width=“fill_parent"

android:layout_height=“400px" android:layout_weight=“1″

android:textColorHighlight=“#cccccc" android:hint=“你想說什麼?"

android:gravity=“top" android:textSize=“18sp">

</EditText>

<Button android:id=“@+id/widget53″ android:layout_width=“100px"

android:layout_height=“wrap_content" android:text=“@string/share"

android:layout_gravity=“right"/>

</LinearLayout>

</ScrollView>

0_1297753550CMCI

從圖中可以看出,上面部分右側有一個滾動條,用戶可以通過從下滾動來點擊按鈕。但是個人覺得,這樣還不如直接關閉輸入法來點擊按鈕來的方便!

 

那麼有沒有更好的辦法呢? 答案是有!

 

先看一下這個更好的方法是什麼效果:

 

從圖中可以看出,UI佈局也與輸入法分離了,同時EditText區域自動縮小了。這樣的話,即不影響用戶輸入,也不影響用戶進一步操作!

 

而且即使打開了輸入法,用戶也可以看到UI全貌,感覺比較舒服、友好。

 

下面就說一下,這個效果是如何做到的.

 

其實答案很簡單,不需要更改局部檔,而是修改AndroidManifest.xml檔,在Activity屬性中加一條:

 

android:windowSoftInputMode=“adjustResize"

 

AndroidManifest.xml修改前後比較:

0_129775418966CA

From:CSDN

共 35 頁    1 33 34 35
共 35 頁    1 33 34 35