Android开发入门之如何使用ListView

ListView是Android经常用到的控件,它用来展示可以滚动的列表。ListView里的列表项是通过adapter来添加的,adapter必须是继承“BaseAdapter”,它的职责是提供数据模型,以及把数据转换成列表项。

Android自带ArrayAdapter、SimpleAdapter和CursorAdapter
ArrayAdapter处理数组或者列表里的数据,通常列表项只有一个文本。
CursorAdapter主要针对数据使用。
SimpleAdapter处理列表里的数据,不同于ArrayAdapter,SimpleAdapter每一个列表项由一个Map对象提供数据。

SimpleAdapter实现ListView的步骤:

1. 定义列表项的layout
2. 准备ListView要显示的数据 ;
3. 把数据添加到数组里;
4. 构建适配器 , 数据适配器 , 动态数组有多少元素就生成多少个列表项;
5. 把适配器 添加到ListView,并显示出来。

1.定义列表项的layout,某一项的layout,并不是整个List的layout。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent"
	android:orientation="horizontal">
	<TextView android:text="TextView" android:id="@+id/accountType"
		android:layout_width="wrap_content" android:layout_height="wrap_content"
		android:paddingLeft="10pt" android:background="#FFFFFF" android:width="30pt"></TextView>
	<TextView android:text="TextView" android:id="@+id/accountNumber"
		android:layout_width="wrap_content" android:layout_height="wrap_content"
		android:paddingLeft="10pt" android:background="#FFFFFF" android:width="60pt"></TextView>
	<TextView android:text="TextView" android:id="@+id/password"
		android:layout_width="wrap_content" android:layout_height="wrap_content"
		android:paddingLeft="10pt"></TextView>
</LinearLayout>

AccountsActivity

package com.eightqiu.secretbox;
 
import java.util.ArrayList;
import java.util.HashMap;
 
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
 
public class AccountsActivity extends Activity {
 
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.passwords);
		ListView listView = (ListView) findViewById(R.id.list_view_passwords);
		ArrayList<HashMap<String, String>> accountInfos = getAccountInfos();
 
		// 4. 构建适配器 , 数据适配器 , 动态数组有多少元素就生成多少个列表项;
		SimpleAdapter simpleAdapter = new SimpleAdapter(this, accountInfos, R.layout.account_info_item, new String[] {
				"accountType", "accountNumber", "password" }, new int[] { R.id.accountType, R.id.accountNumber,
				R.id.password });
 
		// 5. 把适配器 添加到ListView,并显示出来。
		listView.setAdapter(simpleAdapter);
	}
 
	/**
	 * 2.准备ListView要显示的数据; <br>
	 * 3.把数据添加到数组里;
	 **/
	private ArrayList<HashMap<String, String>> getAccountInfos() {
		ArrayList<HashMap<String, String>> accountInfos = new ArrayList<HashMap<String, String>>();
 
		HashMap<String, String> accountInfo1 = new HashMap<String, String>();
		accountInfo1.put("accountType", "qq");
		accountInfo1.put("accountNumber", "335373989");
		accountInfo1.put("password", "132456");
 
		HashMap<String, String> accountInfo2 = new HashMap<String, String>();
		accountInfo2.put("accountType", "email");
		accountInfo2.put("accountNumber", "dinglei@126.com");
		accountInfo2.put("password", "132456");
 
		accountInfos.add(accountInfo1);
		accountInfos.add(accountInfo2);
		return accountInfos;
	}
 
}
Posted in android, 编程开发 | Comments Off

力学增高法

只要是人类,背脊或多或少都有不正常的弯曲。如果把此种(不正常的弯曲)矫正,则各部的关节会伸长,使你的高度增加,你不要小看一个关节由弯曲到伸直能长多少,人体的关节有那么多,积少成多,当然可观。

力学治疗法,不仅对小儿麻痹及半身不遂有显著效果,同时能治疗严重的猫背及O型脚,并使脊椎恢复正常,使体态转好,增加身高。除此之外,也能够治疗妇 女生理的不顺、冷症等。因此,从事于这种美容体操的妇女日益增多。只要每天施行3次,3个月之后,最少能长高3厘米,体态会变得婀娜多姿,可以说是一举两 得的美容体操。

(一)并拢两脚,笔直地站立,把一条腿向后移开半步,然后把上体向前弯曲,不要弯膝盖,使手指能触到地面为止,如此,连续做15~20次。这个动作,可以使大腿及膝盖的线条优美柔和,令左右两腿匀称。

(二)两脚打开30~60厘米,挺直地站立,把一条腿向后退半步,然后把上身扭曲,使指尖能够触及另一侧的脚趾。并连续做10~15次。这个动作,可以使两腕的线条优美柔和,腰围缩小,并矫正脊椎柱的弯曲。

(三)两脚打开60~70厘米,把一条腿向后退半步,再抬起双臂,与肩膀同高,然后把双臂水平地向后甩去。向长腿的方向扭转7次,向短腿的方向扭转4次。这动作,可以使腰围紧缩,体态娇美。

(四)面向墙壁,保持30厘米的距离站住,一条腿向后退半步,脚后跟张开,让足尖朝向内侧,再把两手按在墙壁上,挺起胸部,以臀部向后突起的姿势,并拢着 两个膝盖,曲伸双腿。连续做20~50次。这个动作,可以让股关节有了转位,能治好两腿不匀称的毛病,而且能使腿部线条美丽。

(五)做一个长度乃厘米,阔度约有手腕两倍的腰枕系在腰部,把一条腿向后退半步,深深地坐人椅子里面,再把肩膀向后面靠去,挺起胸部,连续做20次。这个动作,能治好疲劳及肩膀酸痛的毛病,并可以收缩腹部。

(六)拿起一条绳子站立,把一条腿向后退半步,然后,以这种姿势,有韵律地跳跃60~70次。跳绳是一种很好的全身运动,不仅对健康及美容有很大的帮助,同时能收缩全身的肌肉,增加身高。

(七)正坐在小腿上,把一条腿的膝盖向后退3~5厘米,两肩向后扳开,手臂笔直地向上举起,以此姿势,把上体向前倾倒,尽量贴近地板。连续做20~40次。这个动作,是矫正猫背最有效的运动,不仅能使背部挺直,同时能美化腕部的线条。

(八)坐下来,用布条将两膝盖上部绑好,两手抱住小腿,让一条腿的膝盖与另外一条腿的膝盖保持平整一般高,再利用两手拉身体弯曲,使下巴触到膝盖,连续做20~30次,这个动作,可以拉紧臀部肌肉。

(九)做过上述8项运动之后,暂时不要解除膝盖上的布,用一个枕头垫在背部,伸直两腿,躺上15分钟。如果你具有冷症,夜晚可以绑着布条入睡,如此,经过一段时间即可把冷症治愈。对于猫背及O型脚的人来说,这些是最有效的运动。

能增高的食物

如果你现在尚未满25岁(最好先确认你的骨骺线没有闭合),那么只要你遵行下面所说的饮食方法,仍然有机会再增高一点。

要想增高,应该多吃蛋白质,尤其是含有中”胺基酸”的食物,如:面粉、小麦胚芽、豆类、虾、螃蟹、贝类、海藻、牛肉、鸡肉、肝脏、猪腿肉、蛋、牛奶、乳酪及深色蔬菜等。

Posted in 生活笔记 | Comments Off

Happy National Day

Just a quick note to wish everyone a fantastic National Day Holiday. If you’re staying home I hope you have a restful and relaxing holiday enjoying time with friends and family and if you’re traveling I hope you’re travels are safe and smooth. In both cases I hope you all HAVE FUN!!

 

Posted in 英语学习 | Comments Off

Httpclient 4.1.2:Invalid use of SingleClientConnManager: connection still allocated

错误
Exception in thread “main” java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.

只要最后加上EntityUtils.consume(response.getEntity());就可以了!

附SimpleResponseHandler

import java.io.IOException;
 
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils;
 
public class SimpleResponseHandler implements ResponseHandler<Result> {
 
	private HttpClient httpClient = null;
	private String encoding = null;
 
	public SimpleResponseHandler(HttpClient httpClient) {
		this.httpClient = httpClient;
	}
 
	public Result handleResponse(HttpResponse response) throws IOException {
		int statuscode = response.getStatusLine().getStatusCode();
		if (isRedirectStatus(statuscode)) {
			Header header = response.getFirstHeader("location");
			if (header != null) {
				String newuri = header.getValue();
				if ((newuri == null) || (newuri.equals("")))
					newuri = "/";
				if (response.getEntity() != null)
					EntityUtils.consume(response.getEntity());
				return httpClient.doGet(newuri);
			}
		}
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			Result result = new Result(EntityUtils.toString(entity, encoding));
			EntityUtils.consume(entity);
			return result;
		}
		return null;
	}
 
	private boolean isRedirectStatus(int statuscode) {
		return (statuscode == HttpStatus.SC_MOVED_TEMPORARILY) || (statuscode == HttpStatus.SC_MOVED_PERMANENTLY)
				|| (statuscode == HttpStatus.SC_SEE_OTHER) || (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT);
	}
 
}
Posted in java, 编程开发 | Comments Off

HttpClient实现对GZip压缩的Response进行解压

Tomcat、Apache等Web服务器都支持gzip压缩,即响应内容返回给客户端(通常是浏览器,或者HttpClient等)之前先进行压缩,以此来节省宽带占用,网络宽带是瓶颈的集群也会因此而提高响应速度。因为文本在传输过程中是压缩的格式,所以客户端要先进行解压才能解析,若不解压,直接转化,就会出现一段乱码字符串。

现在常用的浏览器也都支持gzip。所以用HttpClient来构造HTTP请求,在数据路转化成字符串之前最好先进行判断是否是压缩格式。

Http-component判断方式和处理方式如下:

private DefaultHttpClient httpClient = new DefaultHttpClient();

httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
public void process(final HttpResponse response, final HttpContext context) throws HttpException,
IOException {
HttpEntity entity = response.getEntity();
Header ceheader = entity.getContentEncoding();
if (ceheader != null) {
for (HeaderElement element : ceheader.getElements()) {
if (element.getName().equalsIgnoreCase("gzip")) {
response.setEntity(new GzipDecompressingEntity(response.getEntity()));
return;
}
}
}
}
});

Note:Http-component的版本要足够高,否则是找不到GzipDecompressingEntity的

Hope you enjoying your work

Posted in java, 编程开发 | Comments Off

跟踪android运行状态日志

如果你不喜欢用android debugger(因为它比较慢,效率不高或者其他原因),那你可以使用StackTraceElement跟踪应用活动记录.

你不需要在每个方法都加上System.out。 只要加上LogUtils.trace(),log就会输出方法名称和代码行数。

Here’s simple sample LogUtils class:

package com.test.log;
 
// !!!!!
// NOTE: enabled log significantly reduces performance
// because it uses high cost getStackTrace() method, which produces huge amounts of objects
// !!!!!
public final class LogUtils {
 
    private static boolean sIsLogEnabled = true;
    private static String sApplicationTag = "LogDemo";
 
    private static final String TAG_FORMAT_METHOD = "%s:%s.%s:%d";
    private static final String FORMAT_METHOD_NAME = "%s:%d";
 
    private static StackTraceElement getCurrentStackTraceElement() {
        return Thread.currentThread().getStackTrace()[4];
    }
 
    public static void trace() {
        if (sIsLogEnabled) {
            android.util.Log.d(getMethodTag(getCurrentStackTraceElement()),
                    getMethodName(getCurrentStackTraceElement()));
        }
    }
 
    private static String getMethodTag(StackTraceElement trace) {
        return String.format(TAG_FORMAT_METHOD, sApplicationTag,
                trace.getClassName(), trace.getMethodName(),
                trace.getLineNumber());
    }
 
    private static String getMethodName(StackTraceElement trace) {
        return String.format(FORMAT_METHOD_NAME, trace.getMethodName(),
                trace.getLineNumber());
    }
 
    public static void traceStack() {
        if (sIsLogEnabled) {
            traceStack(sApplicationTag, android.util.Log.ERROR);
        }
    }
 
    public static void traceStack(String tag, int priority) {
        if (sIsLogEnabled) {
            StackTraceElement[] stackTrace = Thread.currentThread()
                    .getStackTrace();
            if (tag == null) {
                tag = getMethodTag(getCurrentStackTraceElement());
            }
            android.util.Log.println(priority, tag, stackTrace[4].toString());
            StringBuilder str = new StringBuilder();
            String prevClass = null;
            for (int i = 5; i < stackTrace.length; i++) {
                String className = stackTrace[i].getFileName();
                int idx = className.indexOf(".java");
                if (idx >= 0) {
                    className = className.substring(0, idx);
                }
                if (prevClass == null || !prevClass.equals(className)) {
                    str.append(className.substring(0, idx));
                }
                prevClass = className;
                str.append(".").append(stackTrace[i].getMethodName())
                        .append(":").append(stackTrace[i].getLineNumber())
                        .append("->");
            }
            android.util.Log.println(priority, tag, str.toString());
        }
    }
 
}

Activity for example:

package com.test.log;
 
import android.app.Activity;
import android.os.Bundle;
 
public class LogDemoActivity extends Activity {
 
    private void methodB() {
        LogUtils.trace();
        LogUtils.traceStack();
    }
 
    private void methodA() {
        LogUtils.trace();
        methodB();
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        methodA();
    }
}

输出的内容:

?View Code OUTPUT
08-04 13:55:22.020: DEBUG/LogDemo:com.test.log.LogDemoActivity.methodA:13(31856): methodA:13
08-04 13:55:22.020: DEBUG/LogDemo:com.test.log.LogDemoActivity.methodB:9(31856): methodB:9
 
08-04 13:57:25.610: DEBUG/LogDemo:com.test.log.LogDemoActivity.methodA:14(31996): methodA:14
08-04 13:57:25.610: DEBUG/LogDemo:com.test.log.LogDemoActivity.methodB:9(31996): methodB:9
08-04 13:57:25.610: ERROR/LogDemo(31996): com.test.log.LogDemoActivity.methodB(LogDemoActivity.java:10)
08-04 13:57:25.610: ERROR/LogDemo(31996): LogDemoActivity.methodA:15->.onCreate:22->Instrumentation.callActivityOnCreate:1048->ActivityThread.performLaunchActivity:1715->.handleLaunchActivity:1767->.access$1500:122->.handleMessage:1005->Handler.dispatchMessage:99->Looper.loop:132->ActivityThread.main:4028->Method.invokeNative:-2->.invoke:491->ZygoteInit.run:844->.main:602->NativeStart.main:-2->

轻易跟踪应用运行情况
NOTE:不用忘记在Product环境下屏蔽该功能

Posted in android, 编程开发 | Comments Off

liferay关闭js和css缓存

默认情况下,liferay会缓存所有外链形式的js和css,所以不管你在webapps或者temp目录下修改JS或者css文件,都不会即时生效,只有重启tomcat之后才会生效。

但是liferay提供关闭cache的功能,只要改成develop模式即可。

$LIFERAY_HOME/tomcat-6.0.18/webapps/ROOT/WEB-INF/classes/portal-developer.properties

Can copy it and rename it to:

$LIFERAY_HOME/tomcat-6.0.18/webapps/ROOT/WEB-INF/classes/portal-ext.properties

This will disable all caching in Liferay such as css, javascript and vm templates.

Hope this helps.

Posted in java, 编程开发 | Comments Off

快速增肥食谱

每天必须预备的食物如下:

1.鸡蛋(土鸡蛋)
2.高钙牛奶(纸盒装的,250ML一瓶)
3.巧克力饼干(威化饼也行)
4.啤酒(要好点的,5-10块钱一瓶那种)
5.一些卤鸡食品(超市有买,但是不要吃太多)
6,其实主食(粉、面、粥、米饭要换着吃,中餐尽量不要和晚餐吃一样)

快速增肥食谱的详细吃法:(只是零食的吃饭,正餐自己搭配)

早上:两个鸡蛋打在碗里,放5小匙白糖,用开水冲后服用。然后吃包子也行,吃油条也行,不吃可不行。

中午:11点半左右吃午餐,啤酒+米饭,只要要有三个菜,吃饱后再喝一瓶高钙奶。上床午休睡觉至少2个小时。

下午:5点半吃晚饭,面食或者粉类,也要吃饱。吃完后看电视或者看电影,到7点多开始吃卤制品+啤酒,吃完继续看电视。

晚上:11点煮鸡蛋,2-3个。煮10分钟,吃两三个鸡蛋,在吃几颗巧克力饼干,配高钙奶一瓶一起吃掉。

12点之前要睡觉,保证良好的睡眠很重要。

按照我以上的吃法,不出一个月保证见效!其他不说,只要你能坚持每天早上冲两个鸡蛋,效果都会很好的!

如何胖起来

造成人体瘦弱的原因有许多种,从医学角度而言,人体消瘦分为:

*脾胃性消瘦,因脾胃吸收功能低下,营养不能充分吸收,导致身体瘦弱。

*病理性消瘦(由疾病引发所致),导致消瘦的常见疾病有肠道寄生虫、长期活动性结核病、贫血、糖尿病、甲亢、恶性肿瘤、垂体功能减弱症和某些代谢性疾病等。

*复合型消瘦脾胃性与病理性消瘦合并所致。

*精神因素,由于情绪因素,精神焦虑,生活不规律,过度劳累,睡眠不足,身体消耗多于摄入,也是造成瘦弱的直接原因之一。

*饮食因素,饮食不调,缺乏体育锻炼,缺乏营养,尤其是缺乏蛋白质成分。

*遗传和内分泌因素,在遗传、内分泌等因素影响下,其家庭成员都比较瘦,但是没有器质性疾患,精力也很充沛,完全能胜任学习或工作,但易患各种慢性病。

根据人体消瘦病因,科学增肥应有较强的针对性,病理性消瘦必须找出原因,积极消除原发疾病,脾胃性消瘦则应从“培补脾胃”着手,服用一些健脾开胃的中药制剂,通过增强食欲、帮助吸收从而达到增加体重的目的。精神因素和饮食因素就要调整情绪,舒缓压力,改变自己不良的生活习惯,补充充足的营养成分。只有摄入的能量大于消耗的能量,人才能变胖。因此,消瘦者的膳食调配一定要合理、多样,不可偏食。平时除食用富含动物性蛋白质的肉、蛋、禽类外,宜多进食一些含脂肪、碳水化合物(即淀粉、糖类等)较丰富的食物。这样,多余的能量就可以转化为脂肪储存于皮下,使瘦弱者丰满起来。当然,还要适当多吃一些豆制品及赤豆、百合、蔬菜、瓜果等。只有饮食营养全面,才能利于消化吸收。

还应保持充足而良好的睡眠。睡眠若比较充足,胃口就比较好,而且也有利于对食物的消化和吸收。

适当运动。特别是对于那些长期坐办公室的人来说,每天应抽出一定的时间来锻炼,这不仅有利于改善食欲,也能使肌肉更强壮、体魄更健美,人体的肌肉如果长期得不到锻炼,就会“用进废退”,肌纤维相对萎缩,变得薄弱无力,人也就显得瘦弱。

Posted in 生活笔记 | Comments Off

[转载]10大网站运营人员必备定律

作为一名网站运营人员,除了要掌握一些必备的专业知识,如原型策划、交互设计、SEO、以及基本的html代码之外,还应多了解并吸收一些对网站运营有益的营销、商业、心理学等定律,以确保网站能够长期、稳定、正确的发展运营。

今天在论坛里看到一些对“网站运营”很有启发的定律知识, 收集汇总精炼后,帖在博客里,与各位朋友分享:

1.250定律

拉德认为:每一位顾客身后,大体有250名亲朋好友。假如您赢得了一位顾客的好感,就意味着赢得了250个人的好感;反之,假如你得罪了一名顾客,也就意味着得罪了250 名顾客。

在你的网站访客中,一个访客可能可以带来一群访客,任何网站都有起步和发展的过程,这个过程中此定律尤其重要。

2.达维多定律

达维多认为,一个企业要想在市场上总是占据主导地位,那么就要做到第一个开发出新产品,又第一个淘汰自己的老产品。

国内网站跟风太严重,比如前段时间的格子网,乞讨网,博客网,一个成功了,大家一拥而上。但实际效果是,第一个出名的往往最成功,所以在网站的定位上,要动自己的脑筋,不是去捡人家剩下的客户。同理,买人家出售的数据来建站效果是很糟糕的。

3.木桶定律

水桶定律是指,一只水桶能装多少水,完全取决于它最短的那块木板。这就是说任何一个组织都可能面临的一个共同问题,即构成组织的各个部分往往决定了整个组织的水平。

注重审阅自己的网站,是速度最糟糕?美工最糟糕?宣传最糟糕?你首先要做的,不是改进你最强的,而应该是你最薄弱的。

4.马太效应

《新约》中有这样一个故事,一个国王远行前,交给三个仆人每人一锭银子,吩咐他们:“你们去做生意,等我回来时,再来见我。”国王回来时,第一个仆人说: “主人,你交给我们的一锭银子,我已赚了10锭。”于是国王奖励他10座城邑。第二个仆人报告说:“主人,你给我的一锭银子,我已赚了5锭。” 于是国王例奖励了他5座城邑。第三个仆人报告说:“主人,你给我的一锭银子,我一直包在手巾里存着,我怕丢失,一直没有拿出来。”于是国王命令将第三个仆人的一锭银子也赐给第一个仆人,并且说:“凡是少的,就连他所有的也要夺过来。凡是多的,还要给他,叫他多多益善。”这就是马太效应。

在同类网站中,马太效应是很明显的。一个出名的社区,比一个新建的社区,更轻易吸引到新客户。启示是,假如你无法把网站做大,那么你要做专。作专之后再做大就更轻易。

5.手表定理

手表定理是指一个人有一只表时,可以知道现在是几点钟,而当他同时拥有两只表时却无法确定。

一个网站,你只需要关注你特定的用户群需求。不要在意不相干人的看法。

6.不值得定律

不值得定律:不值得做的事情,就不值得做好

不要过度SEO,假如你不是想只做垃圾站。不要把时间浪费在美化再美化页面,优化再优化程序,在你网站能盈利后,这些事情可以交给技术人员完成。

7.彼得原理

劳伦斯.彼得认为:在各种组织中,由于习惯于对在某个等级上称职的人员进行晋升提拔,因而雇员总是趋向于晋升到其不称职的地位。

不要轻易改变自己网站的定位。如博客网想变门户,盛大想做娱乐,大家拭目以待吧。

8.零和游戏原理

当你看到两位对弈者时,你就可以说他们正在玩“零和游戏”。因为在大多数情况下,

总会有一个赢,一个输,假如我们把获胜计算为得1分,而输棋为-1分,那么,这两人得分之和就是:1 (-1)=0 不要把目光一直盯在你的竞争网站上,不要花太多时间抢它的访客。我们把这些时间用来寻找互补的合作网站,挖掘新访客。

9.邦尼人力定律

一个人一分钟可以挖一个洞,六十个人一秒种却挖不了一个洞。合作是一个问题,如何合作也是一个问题。你需要有计划。

10.蘑菇治理

蘑菇治理是许多组织对待初出茅庐者的一种治理方法,初学者被置于阴暗的角落(不受重视的部门,或打杂跑腿的工作),浇上一头大粪(无故的批评、指责、代人受过),任其自生自灭(得不到必要的指导和提携)。

做网站究竟要遭遇这样的阶段,搜索引擎不理你,友情链接找不到,访客不上门。这是磨练。

原文:http://blog.sina.com.cn/s/blog_6290edba0100v1r8.html

Posted in 其他 | Comments Off

java实现图片加水印

图片加水印不仅可以一定程度的防止图片被盗用,也可以起到宣传的作用~ 很多网站、论坛在上传图片时都会自动加上该自己的水印。java提供了强的处理图片的API,所以加水印也是轻而易举的事情。

ImageWatermarking.java

package cn._8qiu.image;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

public class ImageWatermarking {
private Color watermarkColor = Color.BLACK;
private Font font = new Font(“Arial”, Font.PLAIN, 25);
private AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f);
private PositionGenerator positionGenerator = new DefaultPositionGenerator();

public void pressWatermarking(File oldImage, File newImage, String watermark) throws IOException {
ImageIcon icon = new ImageIcon(oldImage.getPath());
BufferedImage bufferedImage = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
g2d.drawImage(icon.getImage(), 0, 0, null);
g2d.setComposite(alpha);
g2d.setColor(watermarkColor);

g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setFont(font);
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds(watermark, g2d);
Position position = positionGenerator.getPosition(icon, rect);
g2d.drawString(watermark, position.getX(), position.getY());
g2d.dispose();
ImageIO.write(bufferedImage, “jpg”, newImage);
}

public void pressWatermarking(String oldImagePath, String newImagePath, String watermark) throws IOException {
pressWatermarking(new File(oldImagePath), new File(newImagePath), watermark);
}

public void setPositionGenerator(PositionGenerator positionGenerator) {
this.positionGenerator = positionGenerator;
}

// some setter methods
}

为易于扩展,定义一个PositionGenerator接口,它用来计算水印的位置。

package cn._8qiu.image; 
import java.awt.geom.Rectangle2D;

import javax.swing.ImageIcon;

public interface PositionGenerator {
public Position getPosition(ImageIcon imageIcon, Rectangle2D fontRect);
}

并且提供一个PositionGenerator的一个默认实现类–DefaultPositionGenerator

package cn._8qiu.image; 

import java.awt.geom.Rectangle2D;

import javax.swing.ImageIcon;

public class DefaultPositionGenerator implements PositionGenerator {

@Override
public Position getPosition(ImageIcon imageIcon, Rectangle2D fontRect) {
int poxX = (imageIcon.getIconWidth() – (int) fontRect.getWidth()) / 2;
int posY = (imageIcon.getIconHeight() – (int) fontRect.getHeight()) / 2;
return new Position(poxX, posY);
}
}

实体类Position.java非常简单

package cn._8qiu.image; 

public class Position {
private int x;
private int y;

public Position(int x, int y) {
this.x = x;
this.y = y;
}

public int getX() {
return x;
}

public void setX(int x) {
this.x = x;
}

public int getY() {
return y;
}

public void setY(int y) {
this.y = y;
}
}

测试方法

public static void main(String[] args) {
ImageWatermarking imageWatermarking = new ImageWatermarking();
String oldImagePath = “E:\\网店\\照片\\第二批\\压缩\\2018-吊带裙\\2018-吊带裙 (1).JPG”;
String newImagePath = “D:\\test.jpg”;
imageWatermarking.setPositionGenerator(new MyPositionGenerator());
try {
imageWatermarking.pressWatermarking(oldImagePath, newImagePath, “hongcaomei.taobao.com”);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Posted in java, 编程开发 | Comments Off