ImageView,和前面介绍的TextView、EditText,都继承自View都是View的子类。
ImageView 是用于呈现图片的视图。View可以理解为一个视图或控件。
1.简单使用
在drawable-xxhdpi文件夹下放一张图片:
xml中把这张图片设置给ImageView,这样就可以在屏幕上看到这张图:
- <ImageView
- android:id="@+id/image_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/girl" />
另外也可以在代码中给ImageView设置图片:
方法1:
- imageView = findViewById(R.id.image_view);
- imageView.setImageResource(R.drawable.girl);
方法2:
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.girl);
- imageView.setImageBitmap(bitmap);
方法1中通过:setImageResource(@DrawableRes int resId)方式,传入一个资源Id,在该方法内会把资源Id加载成一个Drawable。
ImageView.java中
- try {
- d = mContext.getDrawable(mResource);
- } catch (Exception e) {
- Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
- // Don't try again.
- mResource = 0;
- }
方法2中,先把资源Id解析成一个Bitmap,然后把Bitmap设置给ImageView。
imageView.setImageBitmap(bitmap); 这个方法中,也会把传进来的bitmap转换成Drawable。
- mDrawable = null;
- if (mRecycleableBitmapDrawable == null) {
- mRecycleableBitmapDrawable = new BitmapDrawable(mContext.getResources(), bm);
- } else {
- mRecycleableBitmapDrawable.setBitmap(bm);
- }
- setImageDrawable(mRecycleableBitmapDrawable);
以上两种方式都会把生成的Drawable赋值给ImageView的成员变量:Drawable mDrawable
设置完成后,都调用了invalidate();
这会调用父类View的invalidate(),
在View中会调用Parent,也就是ViewRootImpl的invalidate()方法。
在ViewRootImpl的invalidate()方法中,会触发scheduleTraversals,执行遍历,重新 进行布局layout测量measure绘制draw方法。
所以最终会回调到了ImageView的onDraw方法中,ondraw方法中会调用drawable.draw方法。
在draw方法中,传递进来一个画布canvas,最终会把该drawable转成一个bitmap绘制在canvas上,然后交给Native层,在屏幕上进行呈现。
- @Override
- protected void onDraw(Canvas canvas) {
- if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
- mDrawable.draw(canvas);
- } else {
- ........
- mDrawable.draw(canvas);
- .........
-
- }
- }
2.BitmapFactory相关方法介绍:
- //从drable目录下加载一个Bitmap
- BitmapFactory.decodeResource(getResources(), R.drawable.girl);
- //把指定文件解析成一个Bitmap
- BitmapFactory.decodeFile(file);
- //从内存数组中解析成一个Bitmap
- BitmapFactory.decodeByteArray(byteArray,offset,lenght);
- //从流中加载一个Bitmap,
- //这个可以是一个文件流,读取本地的一个缓存文件
- //也可以是一个网络流,从网络获取。
- BitmapFactory.decodeStream(inputStream);
1)从文件中读取一张图片,由于设计到文件io操作,最好是放在子线程中。
示例:通过RxJava读取一张图片到内存。
首先在build.gragle引入Rxjava相关jar包:
- implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
- implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
代码实现:
- public void createBitmap(ImageView imageView,String file) {
- Observable.create(new ObservableOnSubscribe<String>() {
- @Override
- public void subscribe(ObservableEmitter<String> emitter) throws Exception {
- emitter.onNext(file);
- }
- }).subscribeOn(Schedulers.io()).map(new Function<String, Bitmap>() {
-
- @Override
- public Bitmap apply(String file) throws Exception {
- return BitmapFactory.decodeFile(file);
- }
- }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Bitmap>() {
- @Override
- public void accept(Bitmap bitmap) throws Exception {
- imageView.setImageBitmap(bitmap);
- }
- });
- }
2)从网络获取图片示例:
- /**
- * 获取网络图片
- *
- * @param imageurl 图片网络地址
- * @return Bitmap 返回位图
- */
- public Bitmap GetImageInputStream(String imageurl) {
- URL url;
- HttpURLConnection connection = null;
- Bitmap bitmap = null;
- try {
- url = new URL(imageurl);
- connection = (HttpURLConnection) url.openConnection();
- connection.setConnectTimeout(6000); //超时设置
- connection.setDoInput(true);
- connection.setUseCaches(false); //设置不使用缓存
- InputStream inputStream = connection.getInputStream();
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 2;
- options.inJustDecodeBounds = false;
-
- bitmap = BitmapFactory.decodeStream(inputStream, null, options);
- inputStream.close();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return bitmap;
- }
3.BitmapFactory.Options
1)options.inJustDecodeBounds = true;不把图加载到内存,只获取宽高。
- FileInputStream fis = new FileInputStream("fileName");
- BitmapFactory.Options options = new BitmapFactory.Options();
- //为true则只加载图片的大小,返回一个null值,不会把图片加载到内存
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(fis, null, options);
- //得到图片的宽高
- int imgWidth = options.outWidth;
- int imgHeight = options.outHeight;
2) options.inSampleSize = 2; 设置值大于1,加载的图片大小是原理的4分之1,
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = 2;
- Bitmap bitmap = BitmapFactory.decodeFile(imageFile,options);
4.创建Bitmap:Bitmap.createBitmap()
1)代码示例:把View保存到一个bitmap:
- public static Bitmap getBitmapForView(View view) {
- int width = view.getWidth();
- int height = view.getHeight();
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//准备图片
- Canvas canvas = new Canvas(bitmap);//将bitmap作为绘制画布
- view.draw(canvas);//讲View特定的区域绘制到这个canvas(bitmap)上去,
- return bitmap;//得到最新的画布
- }
2)从一个bitmap得到另外一个大小的bitmap
- Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.girl);
- int x = 0;
- int y = 0 ;
- float rate = 1.5f;
- int width = (int) (srcBitmap.getWidth()*rate);
- int height = (int) (srcBitmap.getHeight()*rate);
- Bitmap bitmap = Bitmap.createBitmap(srcBitmap,x,y,width,height);
3)将内存中的一个bitmap保存为一张本地图片:
- Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.girl);
- try {
- FileOutputStream fos = new FileOutputStream("fileName");
- srcBitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }