首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置:
在AndroidManifest.xml中加入访问SDCard的权限如下:
<!-- 在SDCard中创建与删除文件权限 -->
代码如下 |
复制代码 |
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
|
<!-- 往SDCard写入数据权限 -->
代码如下 |
复制代码 |
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
接着我们在使用SDcard进行读写的时候 会用到Environment类下面的几个静态方法
1: getDataDirectory() 获取到Androi中的data数据目录
2:getDownloadCacheDirectory() 获取到下载的缓存目录
3:getExternalStorageDirectory() 获取到外部存储的目录 一般指SDcard
4:getExternalStorageState() 获取外部设置的当前状态 一般指SDcard,
android系统中对于外部设置的状态,我们比较常用的应该是 MEDIA_MOUNTED(SDcard存在并且可以进行读写) MEDIA_MOUNTED_READ_ONLY (SDcard存在,只可以进行读操作) 当然还有其他的一些状态,可以在文档中进行查找到
5:getRootDirectory() 获取到Android Root路径
6:isExternalStorageEmulated() 返回Boolean值判断外部设置是否有效
7:isExternalStorageRemovable() 返回Boolean值,判断外部设置是否可以移除
【注】上面进行红色标记的方法,我们会常用
代码如下 |
复制代码 |
<span style="color:#ff0000;">Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) |
代码中这句:我们对SDcard的状态进行判断,</span>
下面看实现SDCard进行文件读写操作的Demo:
代码如下 |
复制代码 |
package com.jiangqq.sdcard;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class SDcardActivity extends Activity {
private Button bt1, bt2;
private EditText et1, et2;
private static final String FILENAME = "temp_file.txt";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bt1 = (Button) this.findViewById(R.id.bt1);
bt2 = (Button) this.findViewById(R.id.bt2);
et1 = (EditText) this.findViewById(R.id.et1);
et2 = (EditText) this.findViewById(R.id.et2);
bt1.setOnClickListener(new MySetOnClickListener());
bt2.setOnClickListener(new MySetOnClickListener());
}
private class MySetOnClickListener implements OnClickListener {
@Override
public void onClick(View v) {
File file = new File(Environment.getExternalStorageDirectory(),
FILENAME);
switch (v.getId()) {
case R.id.bt1:// 使用SDcard写操作
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(et1.getText().toString().getBytes());
fos.close();
Toast.makeText(SDcardActivity.this, "写入文件成功",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(SDcardActivity.this, "写入文件失败",
Toast.LENGTH_SHORT).show();
}
} else {
// 此时SDcard不存在或者不能进行读写操作的
Toast.makeText(SDcardActivity.this,
"此时SDcard不存在或者不能进行读写操作", Toast.LENGTH_SHORT).show();
}
break;
case R.id.bt2:// 使用SDcard读操作
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
FileInputStream inputStream = new FileInputStream(file);
byte[] b = new byte[inputStream.available()];
inputStream.read(b);
et2.setText(new String(b));
Toast.makeText(SDcardActivity.this, "读取文件成功",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(SDcardActivity.this, "读取失败",
Toast.LENGTH_SHORT).show();
}
} else {
// 此时SDcard不存在或者不能进行读写操作的
Toast.makeText(SDcardActivity.this,
"此时SDcard不存在或者不能进行读写操作", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
}
|
本文章介绍关于在android开发中的图片的浏览、缩放、拖动和自动居中实现实例,有需要的同学可以参考一下下本文章。
Touch.java
代码如下 |
复制代码 |
/**
* 图片浏览、缩放、拖动、自动居中
*/
public class Touch extends Activity implements OnTouchListener {
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
DisplayMetrics dm;
ImageView imgView;
Bitmap bitmap;
float minScaleR;// 最小缩放比例
static final float MAX_SCALE = 4f;// 最大缩放比例
static final int NONE = 0;// 初始状态
static final int DRAG = 1;// 拖动
static final int ZOOM = 2;// 缩放
int mode = NONE;
PointF prev = new PointF();
PointF mid = new PointF();
float dist = 1f;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scale);
imgView = (ImageView) findViewById(R.id.imag);// 获取控件
bitmap = BitmapFactory.decodeResource(getResources(), this.getIntent()
.getExtras().getInt("IMG"));// 获取图片资源
imgView.setImageBitmap(bitmap);// 填充控件
imgView.setOnTouchListener(this);// 设置触屏监听
dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);// 获取分辨率
minZoom();
center();
imgView.setImageMatrix(matrix);
}
/**
* 触屏监听
*/
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 主点按下
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
prev.set(event.getX(), event.getY());
mode = DRAG;
break;
// 副点按下
case MotionEvent.ACTION_POINTER_DOWN:
dist = spacing(event);
// 如果连续两点距离大于10,则判定为多点模式
if (spacing(event) > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - prev.x, event.getY()
- prev.y);
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float tScale = newDist / dist;
matrix.postScale(tScale, tScale, mid.x, mid.y);
}
}
break;
}
imgView.setImageMatrix(matrix);
CheckView();
return true;
}
/**
* 限制最大最小缩放比例,自动居中
*/
private void CheckView() {
float p[] = new float[9];
matrix.getValues(p);
if (mode == ZOOM) {
if (p[0] < minScaleR) {
matrix.setScale(minScaleR, minScaleR);
}
if (p[0] > MAX_SCALE) {
matrix.set(savedMatrix);
}
}
center();
}
/**
* 最小缩放比例,最大为100%
*/
private void minZoom() {
minScaleR = Math.min(
(float) dm.widthPixels / (float) bitmap.getWidth(),
(float) dm.heightPixels / (float) bitmap.getHeight());
if (minScaleR < 1.0) {
matrix.postScale(minScaleR, minScaleR);
}
}
private void center() {
center(true, true);
}
/**
* 横向、纵向居中
*/
protected void center(boolean horizontal, boolean vertical) {
Matrix m = new Matrix();
m.set(matrix);
RectF rect = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight());
m.mapRect(rect);
float height = rect.height();
float width = rect.width();
float deltaX = 0, deltaY = 0;
if (vertical) {
// 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下放留空则往下移
int screenHeight = dm.heightPixels;
if (height < screenHeight) {
deltaY = (screenHeight - height) / 2 - rect.top;
} else if (rect.top > 0) {
deltaY = -rect.top;
} else if (rect.bottom < screenHeight) {
deltaY = imgView.getHeight() - rect.bottom;
}
}
if (horizontal) {
int screenWidth = dm.widthPixels;
if (width < screenWidth) {
deltaX = (screenWidth - width) / 2 - rect.left;
} else if (rect.left > 0) {
deltaX = -rect.left;
} else if (rect.right < screenWidth) {
deltaX = screenWidth - rect.right;
}
}
matrix.postTranslate(deltaX, deltaY);
}
/**
* 两点的距离
*/
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);
}
/**
* 两点的中点
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
}
|
scale.xml
代码如下 |
复制代码 |
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" >
<ImageView
android:id="@+id/imag"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:scaleType="matrix" >
</ImageView>
</FrameLayout>
|
本文章简单的介绍了关于Android SDK安装图文教程,有需要的朋友可以学习一下下哈。好了费话不说多了我们来看看吧。
Android SDK可以通过SDK下载器自动下载和配置,适合网络好,下载速度快的情况下;也可以借助工具下载SDK文件,手工配置,适合网络不是很好,下载速度慢的情况下。
SDK下载器自动下载步骤如下:
1. 解压缩android-sdk_r08-windows下载器,并双击运行SDK Manager.exe:
如果你的电脑不支持https连接会看到如下界面:
请选择setting的将Force https://... Sources to be fetched by using http://... 的选项打勾
2. 勾选你想要安装的Packages,并点击Install Selected进行安装:
3. 确认对话框如下,选择Accept All进行下载安装
4. 则Android SDK下载器进入下载安装的过程
5. 根据你网速的情况,下载安装的时间或长或短,请耐心等待。
本文章简单的android游戏开发实例教程,有需要学习手机游戏开发的朋友可以参考一下下哈。
地图我们创建好了接下来就是主角的出现。其实上文介绍了如何TiledMap和Stage的结合,角色的处理就简单了。
可以继承Actor类创建主角类,我就偷个懒,用Image代替。
编辑我们的TMX文件,添加一个对象层。
在主角要出现的地方加个形状
取名为play1
我们的主角是:
思路是我们遍历map中的所有Object,如果名字和我们设定的play1一致,那么就实例化一个Image,位置和Object一致,添加到舞台。
关键代码:
代码如下 |
复制代码 |
for (TiledObjectGroup group : map.objectGroups) {
for (TiledObject object : group.objects) {
if ("play1".equals(object.name)) {
player = new Image(new TextureRegion(new Texture(Gdx.files
.internal("map/player.png")), 0, 0, 27, 40));
player.x = object.x;
player.y = tileMapRenderer.getMapHeightUnits() - object.y; //map是左上角,Stage是左下角
stage.addActor(player);
}
}
}
|
效果如下:
然后现在来试试让主角动起来。
首先是我们如何控制,android设备的话优先选用触控。如果我们按住前方不放,主角向前。按住上方不放,主角向上。
那么如何确定我们按住的是哪个方向呢?
如图所示,黄色的是Stage,粉红的边框是整个Map,有部分显示,有一部分没有显示。右下角的绿色点是主角的位置,我们假定红色的点是我们的触碰点。
认定红色的触碰点为向前,我在提供一个方案,但是方法不唯一哈,我这样确定方向也不一定是最符合用户体验的。
以主角的位置为原点重现建立坐标系,得到触碰点的新坐标x,y.
确定了在新坐标系下的触碰点的象限,在判断x,y的大小就可以知道方向了。
代码如下:
代码如下 |
复制代码 |
Vector3 tmp = new Vector3(x, y, 0);
stage.getCamera().unproject(tmp);
float newx = tmp.x - player.x;
float newy = tmp.y - player.y;
if (newx > 0 && newy > 0) {
if (newx > newy) {
ChangeDirect(4);
} else {
ChangeDirect(1);
}
} else if (newx > 0 && newy < 0) {
if (newx > -newy) {
ChangeDirect(4);
} else {
ChangeDirect(2);
}
} else if (newx < 0 && newy > 0) {
if (-newx > newy) {
ChangeDirect(3);
} else {
ChangeDirect(1);
}
} else {
if (-newx > -newy) {
ChangeDirect(3);
} else {
ChangeDirect(2);
}
} |
直接移动Camera位置可以移动地图,但是我们的主角却从地图上消失了…处理办法是将你希望仍然显示在地图上的Actor的坐标随着Camera一起移动。
代码如下:
代码如下 |
复制代码 |
private void CameraMove(Vector3 vector3) {
stage.getCamera().position.add(vector3);
for (Actor actor : stage.getActors()) {
actor.x += vector3.x;
actor.y += vector3.y;
}
}
|
完整代码:
代码如下 |
复制代码 |
package com.cnblogs.htynkn.game;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;
import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;
import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;
import com.badlogic.gdx.graphics.g2d.tiled.TiledMap;
import com.badlogic.gdx.graphics.g2d.tiled.TiledObject;
import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectGroup;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
public class firstGame implements ApplicationListener, InputProcessor {
Stage stage;
float width;
float height;
private TiledMap map;
private TileAtlas atlas;
private TileMapRenderer tileMapRenderer;
Image player;
Vector3 camDirection = new Vector3(1, 1, 0);
Vector2 maxCamPosition = new Vector2(0, 0);
Vector3 moveVector = new Vector3(0, 0, 0);
boolean isPress;
// Image image;
@Override
public void create() {
final String path = "map/";
final String mapname = "tilemap";
FileHandle mapHandle = Gdx.files.internal(path + mapname + ".tmx");
map = TiledLoader.createMap(mapHandle);
atlas = new TileAtlas(map, Gdx.files.internal("map/"));
tileMapRenderer = new TileMapRenderer(map, atlas, 10, 10);
maxCamPosition.set(tileMapRenderer.getMapWidthUnits(), tileMapRenderer
.getMapHeightUnits());
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
stage = new Stage(width, height, true);
Label label = new Label("FPS:", new LabelStyle(new BitmapFont(Gdx.files
.internal("font/blue.fnt"),
Gdx.files.internal("font/blue.png"), false), Color.WHITE),
"fpsLabel");
label.y = height - label.getPrefHeight();
label.x = 0;
stage.addActor(label);
for (TiledObjectGroup group : map.objectGroups) {
for (TiledObject object : group.objects) {
if ("play1".equals(object.name)) {
player = new Image(new TextureRegion(new Texture(Gdx.files
.internal("map/player.png")), 0, 0, 27, 40));
player.x = object.x;
player.y = tileMapRenderer.getMapHeightUnits() - object.y; // map是左上角,Stage是左下角
stage.addActor(player);
}
}
}
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(this);
inputMultiplexer.addProcessor(stage);
Gdx.input.setInputProcessor(inputMultiplexer);
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
public void pause() {
// TODO Auto-generated method stub
}
@Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
OrthographicCamera c = (OrthographicCamera) stage.getCamera();
if (isPress) {
CameraMove(moveVector);
}
((Label) stage.findActor("fpsLabel")).setText("FPS: "
+ Gdx.graphics.getFramesPerSecond());
stage.act(Gdx.graphics.getDeltaTime());
tileMapRenderer.render(c);
stage.draw();
}
private void CameraMove(Vector3 vector3) {
stage.getCamera().position.add(vector3);
for (Actor actor : stage.getActors()) {
actor.x += vector3.x;
actor.y += vector3.y;
}
}
@Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void resume() {
// TODO Auto-generated method stub
}
@Override
public boolean keyDown(int keycode) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean keyTyped(char character) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean keyUp(int keycode) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean scrolled(int amount) {
// TODO Auto-generated method stub
return false;
}
private void ChangeDirect(int typeId) {
switch (typeId) {
case 1:
moveVector.set(0, 1, 0);
Gdx.app.log("方向变动", "向上");
break;
case 2:
moveVector.set(0, -1, 0);
Gdx.app.log("方向变动", "向下");
break;
case 3:
moveVector.set(-1, 0, 0);
Gdx.app.log("方向变动", "向左");
break;
case 4:
moveVector.set(1, 0, 0);
Gdx.app.log("方向变动", "向右");
break;
}
}
@Override
public boolean touchDown(int x, int y, int pointer, int button) {
Vector3 tmp = new Vector3(x, y, 0);
stage.getCamera().unproject(tmp);
float newx = tmp.x - player.x;
float newy = tmp.y - player.y;
if (newx > 0 && newy > 0) {
if (newx > newy) {
ChangeDirect(4);
} else {
ChangeDirect(1);
}
} else if (newx > 0 && newy < 0) {
if (newx > -newy) {
ChangeDirect(4);
} else {
ChangeDirect(2);
}
} else if (newx < 0 && newy > 0) {
if (-newx > newy) {
ChangeDirect(3);
} else {
ChangeDirect(1);
}
} else {
if (-newx > -newy) {
ChangeDirect(3);
} else {
ChangeDirect(2);
}
}
isPress = true;
return false;
}
@Override
public boolean touchDragged(int x, int y, int pointer) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean touchMoved(int x, int y) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean touchUp(int x, int y, int pointer, int button) {
isPress = false;
Gdx.app.log("Info", "touchUp: x:" + x + " y: " + y + " pointer: "
+ pointer + " button: " + button);
return false;
}
}
|
本文章介绍了一篇关于手机开发中的android开时的 ui高效做法,有需要了解的朋友可以参考一下下哦。
一、选择恰当的图像尺寸
视图背景图总是会填充整个视图区域,图像尺寸的不适合会导致图像的自动缩放,为了避免这种情况,我们可以先将图片进行缩放到视图的大小。
代码如下 |
复制代码 |
originalImage = Bitmap.createScaledBitmap(
originalImage, //被缩放图
view.getWidth(), //视图宽度
view.getHright(), //视图高度
true //双限行过滤器
);
|
二、去掉不需要的默认窗口背景
在默认情况下,窗口有一个不透明的背景,有时候我们并不需要他,就可以去掉他。因为更新看不见的窗口是浪费时间的。
去掉的方法:
1.代码实现:
代码如下 |
复制代码 |
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//删除窗口背景
getWindow().setBackgroundDrawable(null);
}
|
2.xml里实现:
首先去顶你的res/xml/styles.xml里有
代码如下 |
复制代码 |
<resources>
<style name="NoBackGroundTheme" parent="android:Theme">
<item name="android:windowBackground">@null</item>
</style>
</resources>
然后在你的manifest.xml里声明
<activity android:name="MyActivity" android:theme="@style/NoBackGroundTheme">
......
</activity>
|
三、尽可能的使用简单的布局和视图
如果一个窗口包含很多的视图,那么启动时间长、测量时间长、绘制时间长、布局时间长;
如果视图树深度太深,会导致StackOverflowException异常,和用户界面反映会很慢很慢。
解决的方法:
1.使用TextView的复合drawables,减少层次
如有这样的布局:
代码如下 |
复制代码 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/hello" />
<Image android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/image" android:background="@drawable/icon" />
</LinearLayout>
|
我们可以这样来取代他,从而来将少层次:
代码如下 |
复制代码 |
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/hello" android:drawableRight="@drawable/icon"/>
|
2.使用ViewStub延迟展开视图
默认情况下,使用ViewStub包含的视图是不可见的。
代码如下 |
复制代码 |
<ViewStub android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/vs" android:layout="@layout/main"/>
|
这个里面包含的main视图是不会展现出来的,如果需要展现出来需要代码的处理
代码如下 |
复制代码 |
findViewById(R.id.vs).setVisibility(View.VISIBLE);
者
findViewById(R.id.vs).inflate();
|
3.使用<merge>合并视图
默认情况下,布局文件的根作为一个借点加入到父视图中,如果使用<merge>可以避免根节点。
如果最外层的布局是FrameLayout,那么可以使用merge替换掉,引用官方说明:
Obviously, using <merge /> works in this case because the parent of an activity's content view is always a FrameLayout. You could not apply this trick if your layout was using a LinearLayout as its root tag for instance.
代码如下 |
复制代码 |
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
.....
</merge>
|
4.使用RelativeLayout减少层次
5.自定义布局
标签:[!--infotagslink--]