当前位置:  编程技术>移动开发
本页文章导读:
    ▪图片缩放、压缩、封存        图片缩放、压缩、保存 在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用 BitmapFactory的decodeFile.........
    ▪ 自定义Adapter写法记要        自定义Adapter写法记录   package com.example.coolvidaoplayer; import java.util.List; import java.util.Map; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import and.........
    ▪ 界别Activity的四种加载模式-activity       区分Activity的四种加载模式-activity 转载:http://marshal.easymorse.com/archives/2950   在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity。可能会希望跳转到原.........

[1]图片缩放、压缩、封存
    来源: 互联网  发布时间: 2014-02-18
图片缩放、压缩、保存

在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用 BitmapFactory的decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几 分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。 
  然而,如果我们想取固定大小的缩略 图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么办?我们总不能将原始图片加载到内存中再 进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止 100K?
  经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的 
   If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels. 
  意思就是说如果该值设为 true那么将不返回实际的bitmap不给其分配内存空间而里面只包括一些解码边界信息即图片大小信息,那么相应的方法也就出来了,通过设置 inJustDecodeBounds为true,获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize 可能小于0,必须做判断。 
具体代码如下: 
FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01); 
        BitmapFactory.Options options = new BitmapFactory.Options(); 
        options.inJustDecodeBounds = true; 
        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test.jpg", options); //此时返回bm为空 
        options.inJustDecodeBounds = false; 
         //缩放比 
        int be = (int)(options.outHeight / (float)200); 
        if (be <= 0) 
            be = 1; 
        options.inSampleSize = be; 
        //重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦 
        bitmap=BitmapFactory.decodeFile("/sdcard/test.jpg",options); 
        int w = bitmap.getWidth(); 
        int h = bitmap.getHeight(); 
        System.out.println(w+"   "+h); 
        ImageView iv=new ImageView(this); 
        iv.setImageBitmap(bitmap); 
这样我们就可以读取较大的图片而不会内存溢出了。如果你想把压缩后的图片保存在Sdcard上的话就很简单了: 
File file=new File("/sdcard/feng.png"); 
        try { 
            FileOutputStream out=new FileOutputStream(file); 
            if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){ 
                out.flush(); 
                out.close(); 
            } 
        } catch (FileNotFoundException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } catch (IOException e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 

ok,这样就把图片保存在/sdcard/feng.png这个文件里面了,呵呵。 

但是这里的缩放保存是按长宽比例的,下边也可以按固定大小缩放哦: 

        int bmpWidth  = bitmap.getWidth();  

        int bmpHeight = bitmap.getHeight();  

          

        //缩放图片的尺寸  

        float scaleWidth  = (float) sWidth / bmpWidth;     //按固定大小缩放  sWidth 写多大就多大 

        float scaleHeight = (float) sHeight / bmpHeight;  // 

        Matrix matrix = new Matrix();  

        matrix.postScale(scaleWidth, scaleHeight);  

          

        //产生缩放后的Bitmap对象  

        Bitmap resizeBitmap = Bitmap.createBitmap(  

            bitmap, 0, 0, bmpWidth, bmpHeight, matrix, false);  

        bitmap.recycle();  

                Bitmap resizeBitmap = bitmap;  

        //Bitmap to byte[]  

        byte[] photoData = bitmap2Bytes(resizeBitmap);  

        

        //save file  

        String fileName = "/sdcard/test.jpg";  

        FileUtil.writeToFile(fileName, photoData);



引用
压缩图片质量:     
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fos);     
其中的quality为0~100, 可以压缩图片质量, 不过对于大图必须对图片resize    
  
这个是等比例缩放:  
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);  
  
这个是截取图片某部分:  
bitmap = Bitmap.createBitmap(bitmap, x, y, width, height);  
  
这几个方法都是针对Bitmap的, 不过鉴于Bitmap可以从file中读取, 也可以写入file.    
  
这是我知道Android自带库里中唯一可以缩放和压缩的图片方法. 

    
[2] 自定义Adapter写法记要
    来源: 互联网  发布时间: 2014-02-18
自定义Adapter写法记录

 

package com.example.coolvidaoplayer;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class VidaoListAdapter extends BaseAdapter {
	private LayoutInflater videoListInflater;
	private List<Map<String,Object>>videoList;
	public VidaoListAdapter(Context context,List<Map<String,Object>>list)
	{
		this.videoListInflater=LayoutInflater.from(context);
		this.videoList=list;
	}
	static class ViewHolder{
		ImageView ivVideoThumbnail;
		TextView tvVideoName;
		TextView tvVideoSize;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		if(videoList!=null)
		{
			return videoList.size();
		}else
		return 0;
	}

	@Override
	public Object getItem(int pos) {
		// TODO Auto-generated method stub
		return videoList.get(pos);
	}

	@Override
	public long getItemId(int id) {
		// TODO Auto-generated method stub
		return id;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		ViewHolder videoHolder=null;
		if(convertView==null)
		{
			videoHolder=new ViewHolder();
			convertView=videoListInflater.inflate(R.layout.list_item_vidaoinfo, null);
			videoHolder.ivVideoThumbnail=(ImageView)convertView.findViewById(R.id.iv_vidao_thumbnail);
			videoHolder.tvVideoName=(TextView)convertView.findViewById(R.id.tv_vidao_name);
			videoHolder.tvVideoSize=(TextView)convertView.findViewById(R.id.tv_vidao_size);
			videoHolder.ivVideoThumbnail.setBackgroundResource((Integer)videoList.get(position).get("videothumbnail"));
			videoHolder.tvVideoName.setText((String)videoList.get(position).get("videoname"));
			videoHolder.tvVideoSize.setText((String)videoList.get(position).get("videosize"));
			convertView.setTag(videoHolder);
		}
		else
		{
			videoHolder=(ViewHolder)convertView.getTag();
		}
		
		return convertView;

	}

}

    
[3] 界别Activity的四种加载模式-activity
    来源: 互联网  发布时间: 2014-02-18
区分Activity的四种加载模式-activity

转载:http://marshal.easymorse.com/archives/2950

 

在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity。可能会希望跳转到原来某个Activity实例,而不是产生大量重复的Activity。

这需要为Activity配置特定的加载模式,而不是使用默认的加载模式。

加载模式分类及在哪里配置

Activity有四种加载模式:

  • standard
  • singleTop
  • singleTask
  • singleInstance

设置的位置在AndroidManifest.xml文件中activity元素的android:launchMode属性:

<activity android:name="ActB" android:launchMode ="singleTask"></activity>

也可以在Eclipse ADT中图形界面中编辑:

 

区分Activity的加载模式,通过示例一目了然。这里编写了一个Activity A(ActA)和Activity B(ActB)循环跳转的例子。对加载模式修改和代码做稍微改动,就可以说明四种模式的区别。

standard

首先说standard模式,也就是默认模式,不需要配置launchMode。先只写一个名为ActA的Activity:

    package com.easymorse.activities;

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.TextView;

    public class ActA extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            TextView textView = new TextView(this);
            textView.setText(this + "");
            Button button = new Button(this);
            button.setText("go actA");
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setClass(ActA.this, ActA.class);
                    startActivity(intent);
                }
            });
            LinearLayout layout = new LinearLayout(this);
            layout.setOrientation(LinearLayout.VERTICAL);
            layout.addView(textView);
            layout.addView(button);
            this.setContentView(layout);
        }
    }
 

例子中都没有用layout,免得看着罗嗦。可见是ActA –> ActA的例子。在界面中打印出对象的toString值可以根据hash code识别是否创建新ActA实例。

第一个界面:

点击按钮后:

可以多点几次。发现每次都创建了该Activity的新实例。standard的加载模式就是这样的,intent将发送给新的实例。

现在点Android设备的回退键,可以看到是按照刚才创建Activity实例的倒序依次出现,类似退栈的操作,而刚才操作跳转按钮的过程是压栈的操作。如下图:

singleTop

singleTop和standard模式,都会将intent发送新的实例(后两种模式不发送到新的实例,如果已经有了的话)。不 过,singleTop要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不发送给新的实例。

还是用刚才的示例,只需将launchMode改为singleTop,就能看到区别。

运行的时候会发现,按多少遍按钮,都是相同的ActiA实例,因为该实例在栈顶,因此不会创建新的实例。如果回退,将退出应用。

singleTop模式,可用来解决栈顶多个重复相同的Activity的问题。

如果是A Activity跳转到B Activity,再跳转到A Activity,行为就和standard一样了,会在B Activity跳转到A Activity的时候创建A Activity的新实例,因为当时的栈顶不是A Activity实例。

ActA类稍作改动:

package com.easymorse.activities;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ActA extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textView = new TextView(this);
        textView.setText(this + "");
        Button button = new Button(this);
        button.setText("go actB");
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClass(ActA.this, ActB.class);
                startActivity(intent);
            }
        });
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.addView(textView);
        layout.addView(button);
        this.setContentView(layout);
    }
}
 

 

ActB类:

package com.easymorse.activities;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;

public class ActB extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         Button button=new Button(this);
            button.setText("go actA");
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent();
                    intent.setClass(ActB.this, ActA.class);
                    startActivity(intent);
                }
            });
            LinearLayout layout=new LinearLayout(this);
            layout.addView(button);
            this.setContentView(layout);
    }
}
 

 

ActB类使用默认(standard)加载,ActA使用singleTop加载。结果类似下图:

如果把ActA的加载模式改为standard,情况一样。

singleTask

singleTask模式和后面的singleInstance模式都是只创建一个实例的。

当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。

把上面singleTop的实例中的ActA的launchMode改为singleTask,ActB的改为standard。那么会发现在ActA界面中按一次按钮:

然后在ActB1界面中按按钮,因为ActA是singleTask,会使用原来的ActA1实例。这时候栈内的情况:

如果多次按按钮跳转,会发现始终只有ActA1这一个ActA类的实例。

singleInstance

解释singleInstance模式比较麻烦。

首先要说一下Task(任务)的概念。

如果是Swing或者Windows程序,可能有多个窗口可以切换,但是你无法在自己程序中复用人家的窗口。注意是直接复用人家的二进制代码,不是你拿到人家api后的源代码级调用。

Android可以做到,让别人的程序直接复用你的Activity(类似桌面程序的窗口)。

Android为提供这种机制,就引入了Task的概念。Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么 Android就创建了一个Task,然后启动这个应用的入口Activity,就是intent-filter中配置为main和launch的那个 (见一个APK文件部署产生多个应用安装的效果 )。这个Activity是根(Root)Activity,可能会在它的界面调用其他Activity,这些Activity如果按照上面那三个模式,也会在这个栈(Task)中,只是实例化的策略不同而已。

验证的办法是调用和打印Activity的taskId:

TextView textView2 = new TextView(this);
textView2.setText("task id: "+this.getTaskId());

会发现,无论切换Activity,taskId是相同的。

当然也可以在这个单一的Task栈中,放入别人的Activity,比如google地图,这样用户看过地图按回退键的时候,会退栈回到调用地图的Activity。对用户来说,并不觉得在操作多个应用。这就是Task的作用。

但是,有这样的需求,多个Task共享一个Activity(singleTask是在一个task中共享一个Activity)。

现成的例子是google地图。比如我有一个应用是导游方面的,其中调用的google地图Activity。那么现在我比如按home键,然后到应用列表中打开google地图,你会发现显示的就是刚才的地图,实际上是同一个Activity。

如果使用上面三种模式,是无法实现这个需求的。google地图应用中有多个上下文Activity,比如路线查询等的,导游应用也有一些上下文Activity。在各自应用中回退要回退到各自的上下文Activity中。

singleInstance模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。

这里又有两个问题:

  • 如果是这种情况,多个task栈也可以看作一个应用。比如导游应用启动地图Activity,实际上是在导游应用task栈之上 singleInstance模式创建的(如果还没有的话,如果有就是直接显示它)一个新栈,当这个栈里面的唯一Activity,地图Activity 回退的时候,只是把这个栈移开了,这样就看到导游应用刚才的Activity了;
  • 多个应用(Task)共享一个Activity要求这些应用都没有退出,比如刚才强调要用home键从导游应用切换到地图应用。因为,如果退出导游应用,而这时也地图应用并未运行的话,那个单独的地图Activity(task)也会退出了。

如果还是拿刚才的ActA和ActB的示例,可以把ActB的模式改为singleInstance,ActA为standard,如果按一次按钮切换到ActB,看到现象用示意图类似这样:

如果是第一次按钮切换到ActB,在ActB在按按钮切换到ActA,然后再回退,示意图是:

另外,可以看到两个Activity的taskId是不同的


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3