第六篇Android--ImageView、Bitmap

ImageView,和前面介绍的TextView、EditText,都继承自View都是View的子类。

ImageView 是用于呈现图片的视图。View可以理解为一个视图或控件。

1.简单使用

   在drawable-xxhdpi文件夹下放一张图片:

   

  xml中把这张图片设置给ImageView,这样就可以在屏幕上看到这张图:

      

  另外也可以在代码中给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() {
            @Override
            public void subscribe(ObservableEmitter emitter) throws Exception {
                emitter.onNext(file);
            }
        }).subscribeOn(Schedulers.io()).map(new Function() {

            @Override
            public Bitmap apply(String file) throws Exception {
                return BitmapFactory.decodeFile(file);
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer() {
            @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();
        }

你可能感兴趣的:(Android开发从基础到高级,android)