0.前言
这个学期有嵌入式的课程,需要做一个嵌入式的成品,本来我不想做带系统的东西,但老师说了,上海是服务型的城市,我知道你们怕带系统的东西,做带系统的比较好Balabalabala……好吧,按老师的要求,我们准备做安卓下的电子相册,图片从外部存储SD卡上读取(很搞笑诶,做个相册需要用安卓么,纯粹为了学习)
之前一直没接触过安卓,前期查了点资料,开始起步学习Android,准备用控件Gallery,之后发现该控件“Deprecated since API level16“也就是Android4.1.2,但网络上Gallery的资料比较多,对于我这个新手比较好入手,大体效果如下:
测试系统:MIUI-4.4.4,Android-4.1.1
1.布局
首先在布局文件中加入两个Gallery,上面的叫biggallery,由于原有的Gallery一滑动就会滑过许多格,要实现一次滑一屏的效果,我们写了自定义的myGallery类,继承Gallery,下面缩略图的是原有的Gallery
布局文件如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context="com.example.test.MainActivity$PlaceholderFragment" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.test.myGallery android:id="@+id/biggalleryid" android:layout_width="fill_parent" android:background="#000000" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:gravity="center_vertical" android:spacing="5dip"/> <Gallery android:id="@+id/galleryid" android:layout_width="fill_parent" android:background="#000000" android:layout_height="80dip" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:gravity="center_vertical" android:spacing="1dip"/> </RelativeLayout>
新建一个myGallery类继承Gallery:
package com.example.test; import android.content.Context; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.widget.Gallery; public class myGallery extends Gallery { public myGallery(Context context) { super(context); this.setStaticTransformationsEnabled(true); } public myGallery(Context context, AttributeSet attrs) { super(context, attrs); this.setStaticTransformationsEnabled(true); } public myGallery(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setStaticTransformationsEnabled(true); } private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) { return e2.getX() > e1.getX(); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // e1是按下的事件,e2是抬起的事件 int keyCode; if (isScrollingLeft(e1, e2)) { keyCode = KeyEvent.KEYCODE_DPAD_LEFT; } else { keyCode = KeyEvent.KEYCODE_DPAD_RIGHT; } onKeyDown(keyCode, null); return true; } }
建立好了两个Gallery,接下来,我们需要读取外部SD卡中的图片了,我是通过把图片的路径放入一个List中实现的,由getpicpath(String sdpath)来实现。我感觉这个应用比较难的地方是顺畅地加载图片,我们知道从外部SD卡读取图片是慢的,从缓存中直接读是比较快的,还有一点就是现在的相机像素都比较高,加载照片就容易慢。对于加载慢的这个问题,我们可以在程序onCreat()的时候先把缩略图加载进内存(注意要是缩略图,不然容易造成内存溢出),供下面的Gallery使用;之前,我不是这么做的,我是在滑动的时候进行图片解码decodeSampledBitmapFromFile(),这样的话,滑动一次就要解码加载一次,快速滑动的话会连续加载沿路的图片,还会更加地卡。
4.加载适配器
我们加载好图片、建立好Gallery之后,怎么把这两者联系起来呢,一个是数据源,一个是视图View,这中间要有一个适配器,我们可以使用一个继承自BaseAdapter类的派生类ImageAdapter来装这些图片。
在ImageAdapter类中我们需要实现Adapter类中的如下四个抽象方法:
(1)public int getCount();
(2)public Object getItem(int position);
(3)public long getItemId(int position);
(4)public View getView(int position, View convertView, ViewGroup parent);
其中,getCount()方法用于获取ImageAdapter适配器中图片个数;getItem()方法用于获取图片在ImageAdapter适配器中的位置;getItemId()方法用于获取图片在ImageAdapter适配器中位置;getView()用于获取ImageAdapter适配器中指定位置的视图对象。
MainActivity类如下:
package com.example.test; import java.io.File; import java.util.ArrayList; import java.util.List; import android.app.ActionBar.LayoutParams; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.support.v4.util.LruCache; import android.support.v7.app.ActionBarActivity; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.AdapterView; import android.widget.Gallery; import android.widget.ImageSwitcher; import android.widget.ImageView; import android.widget.ViewSwitcher.ViewFactory; public class MainActivity extends ActionBarActivity /*implements ViewFactory*/{ private List<String> photolist = new ArrayList<String>(); private myGallery biggallery; private Gallery gallery; private ImageAdapter imageAdapter; private BigImageAdapter bigimageAdapter; private int galleryItemBackground; private String newFilePath; private int downX,upX; private LruCache<String, Bitmap> dateCache; private int motionStatus; private SensorManager sensormanager; private Sensor lightsensor,orientationsensor,accelerometersensor; private String sen; private int delay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_main); //获得传感器列表 sensormanager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); List<Sensor> sensors = sensormanager.getSensorList(Sensor.TYPE_ALL); for(Sensor sensor:sensors) sen = sensor.getName(); lightsensor = (Sensor)sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT); accelerometersensor = (Sensor)sensormanager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); orientationsensor = (Sensor)sensormanager.getDefaultSensor(Sensor.TYPE_ORIENTATION); //获得所有图片路径 String sdpath = Environment.getExternalStorageDirectory()+"/DCIM/Camera/"; getpicpath(sdpath); //gallery设置背景 TypedArray a = obtainStyledAttributes(R.styleable.Gallery1); galleryItemBackground = a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 0); a.recycle(); //new一个缓存 dateCache = new LruCache<String, Bitmap>(photolist.size()); gallery = (Gallery)findViewById(R.id.galleryid); biggallery = (myGallery)findViewById(R.id.biggalleryid); imageAdapter = new ImageAdapter(photolist,this,galleryItemBackground); gallery.setAdapter(imageAdapter); bigimageAdapter = new BigImageAdapter(photolist,this,0); biggallery.setAdapter(bigimageAdapter); gallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> arg0, View arg1,int position, long when){ imageAdapter.setSelectItem(position); biggallery.setSelection(position); } public void onNothingSelected(AdapterView<?> arg0) {} }); biggallery.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> arg0, View arg1,int position, long when){ // gallery.setSelection(position); } public void onNothingSelected(AdapterView<?> arg0) {} }); } protected void onResume() { sensormanager.registerListener(new SensorEventListener(){ public void onSensorChanged(SensorEvent event){ // float value0 = event.values[0]; // float value1 = event.values[1]; float value2 = event.values[2]; System.out.println("value2:"+value2); delay += value2; if((value2<10)&&(value2>-10))delay=0; if(delay>100){ delay=0; if(imageAdapter.getShowingIndex()!=0) gallery.setSelection(imageAdapter.getShowingIndex()-1); } if(delay<-100){ delay=0; if(imageAdapter.getShowingIndex()!=imageAdapter.getCount()-1) gallery.setSelection(imageAdapter.getShowingIndex()+1); } } public void onAccuracyChanged(Sensor sensor,int accuracy){ } },orientationsensor,sensormanager.SENSOR_DELAY_UI); super.onResume(); } protected void onPause() { //注销所有传感器的监听 // sensormanager.unregisterListener(); super.onPause(); } private class MyTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { /*int showing = adapter.getShowingIndex();// 记录当前正在显示图片的id Bitmap[] bitmaps = adapter.getNearBitmaps();//获得Adapter中的缓存图片数组 BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; if(motionStatus==-1){//向前滑动,bitmaps[0]加载新的图片 bitmaps[2]=bitmaps[1]; bitmaps[1]=bitmaps[0]; if(showing>=2) bitmaps[0]=BitmapFactory.decodeResource(getResources(), imagesId[showing - 2], options); } if(motionStatus==1){//向后滑动,bitmaps[2]加载新的图片 bitmaps[0]=bitmaps[1]; bitmaps[1]=bitmaps[2]; if(showing<=imagesId.length-3) bitmaps[2]=BitmapFactory.decodeResource(getResources(), imagesId[showing + 2], options); } adapter.setShowingIndex(showing+motionStatus);*/ return null; } } /* * 注册一个触摸事件 */ private OnTouchListener touchListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_DOWN) { downX=(int) event.getX();//取得按下时的坐标 return true; } else if(event.getAction()==MotionEvent.ACTION_UP) { upX=(int) event.getX();//取得松开时的坐标 int index=0; if(upX-downX>70)//从左拖到右,即看前一张 { //如果是第一,则去到尾部 if(gallery.getSelectedItemPosition()==0) index=gallery.getCount()-1; else index=gallery.getSelectedItemPosition()-1; //改变gallery图片所选,自动触发ImageSwitcher的setOnItemSelectedListener biggallery.setSelection(index, true); } else if(downX-upX>70)//从右拖到左,即看后一张 { //如果是最后,则去到第一 if(gallery.getSelectedItemPosition()==(gallery.getCount()-1)) index=0; else index=gallery.getSelectedItemPosition()+1; gallery.setSelection(index, true); } return true; } return false; } }; //以下三个函数的作用:获取所有图片的路径,并放入LIST中 private String isSdcard(){ File sdcardDir=null; boolean isSDExist=Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); if(isSDExist){ sdcardDir=Environment.getExternalStorageDirectory(); return sdcardDir.toString(); } else{ return null; } } // public void getpicpath(String sdpath){ //打开SD卡目录 File file = new File(sdpath); //获取SD卡目录列表 File[] files =file.listFiles(); for(int z=0;z<files.length;z++){ File f = files[z]; if(f.isFile()){ isfile(f); } /*else{ notfile(f); }*/ } } //若是文件 public void isfile(File file){ String filename=file.getName(); int idx = filename.lastIndexOf("."); if (idx <= 0) { return; } String suffix =filename.substring(idx+1, filename.length()); if (suffix.toLowerCase().equals("jpg") || suffix.toLowerCase().equals("jpeg") || suffix.toLowerCase().equals("bmp") || suffix.toLowerCase().equals("png") || suffix.toLowerCase().equals("gif") ){ // mapsd.put("imagepath",file.getPath().toString()); String filestring = file.getPath().toString(); photolist.add(filestring); } } }