存档在 2015年10月

Android在ListView中嵌套一个GridView时只显示一行的原因及解决方法

2015年10月5日

在之前的编程里,我还没有遇到过要在一个ListView中嵌套一个GridView或是在一个GridView中嵌套一个ListView。所以今天事儿来了!我花了一将近3个小时,找到了为什么我在一个ListView中添加一个GridView时,只显示一行GridView的原因;另外,这3个小时的付出,又让我学会了另一件事——在局部找不到原因的时候,要跳出来,从更大的范围寻找原因。废话了这么多,那么究竟是为什么只显示一行GridView呢?

因为在Android中,有这样一个限制,两ScrollView型的控件不能相互嵌套。像ListView和GridView就都是ScrollView型的控件。因为嵌套后,两个ScrollView型控件的滑动效果就丧失了,同时被嵌套控件的高度也被限定为一行的高度。那我们还能不能嵌套两个ScrollView型的控件呢?肯定是可以的。方法有两种:一是我们去需要自定义ListView或是GridView,并重写其onMeasure()方法。

如下:

public class NoScrollGridView extends GridView { 
	public NoScrollGridView(Context context) { 
		super(context); 
	} 
	public NoScrollGridView(Context context, AttributeSet attrs) { 
		super(context, attrs); 
	}

	@Override 
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
		int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST); 
		super.onMeasure(widthMeasureSpec, expandSpec); 
	}
}

ListView也同理。
还有一种方法是我们重新动态地计算我们现在需要的高度。在我们调用Adapter的时候,我们获得现在这个时候的GridView有多少个,单个GridView的高度,然后计算总高度。具体代码如下:

/**
	 * 重新计算listView高度
	 * @param listView
	 */
	public static void setListViewHeightBasedOnChildren(ListView listView) {
		// 获取ListView对应的Adapter
		ListAdapter listAdapter = listView.getAdapter();
		if (listAdapter == null) {
			return;
		}

		int totalHeight = 0;
		for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目
			View listItem = listAdapter.getView(i, null, listView);
			listItem.measure(0, 0); // 计算子项View 的宽高
			totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
		}

		ViewGroup.LayoutParams params = listView.getLayoutParams();
		params.height = totalHeight
				+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
		// listView.getDividerHeight()获取子项间分隔符占用的高度
		// params.height最后得到整个ListView完整显示需要的高度
		listView.setLayoutParams(params);
	}

在我们setAdapter()的之前,我们调用上面的方法,如setListViewHeightBasedOnChildren(accomplishmentStateListView);
因为我是在ListView中嵌套GridView,所以重新计算GridView的总高度的时候,要放在setAdapter(…GridViewAdapter)这个BaseAdapter的衍生类里。代码如下:

/**
	 * 计算gridview高度
	 * @param gridView
	 */
	public static void setGridViewHeightBasedOnChildren(GridView gridView) {
		// 获取GridView对应的Adapter
		ListAdapter listAdapter = gridView.getAdapter();
		if (listAdapter == null) {
			return;
		}
		int rows;
		int columns = 0;
		int horizontalBorderHeight = 0;
		Class<?> clazz = gridView.getClass();
		try {
			// 利用反射,取得每行显示的个数
			Field column = clazz.getDeclaredField("mRequestedNumColumns");
			column.setAccessible(true);
			columns = (Integer) column.get(gridView);
			// 利用反射,取得横向分割线高度
			Field horizontalSpacing = clazz
					.getDeclaredField("mRequestedHorizontalSpacing");
			horizontalSpacing.setAccessible(true);
			horizontalBorderHeight = (Integer) horizontalSpacing.get(gridView);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		// 判断数据总数除以每行个数是否整除。不能整除代表有多余,需要加一行
		if (listAdapter.getCount() % columns > 0) {
			rows = listAdapter.getCount() / columns + 1;
		} else {
			rows = listAdapter.getCount() / columns;
		}
		int totalHeight = 0;
		for (int i = 0; i < rows; i++) { // 只计算每项高度*行数
			View listItem = listAdapter.getView(i, null, gridView);
			listItem.measure(0, 0); // 计算子项View 的宽高
			totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
		}
		ViewGroup.LayoutParams params = gridView.getLayoutParams();
		params.height = totalHeight + horizontalBorderHeight * (rows - 1);// 最后加上分割线总高度
		gridView.setLayoutParams(params);
	}

这样我们就可以在ListView中添加GridView了。。。
注:两个SrcollView型的控件可以是:
;
;
;
;
;
;
;
;
;
… …

ANDROID SHAPE画圆形背景实现圆形TextView

2015年10月5日

shape可以绘制矩形环形以及椭圆、所以只需要用椭圆就可以完成需求、在使用的时候将控件比如textview的高宽设置成一样就是正圆、solid表示远的填充色、stroke则代表远的边框线、所以两者结合可以实现带边缘的圆、Shape 代码

<?xml version="1.0" encoding="UTF-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false" >
    <solid android:color="@color/base_color" />
    <padding
        android:left="2dp"
        android:top="1dp"
        android:right="2dp"
        android:bottom="1dp" />
    <solid
        android:color="@color/green" />
    <stroke
        android:width="1dp"
        android:color="@android:color/white" />
    <size android:width="25dp"
        android:height="25dp" />
</shape>

把以上代码添加到drawable里面、通过background引用就可以了

<TextView
        android:id="@ id/message_category_unread_count"
        style="@style/comm_text_style_14_aaaaaa"
        android:layout_marginLeft="70dp"
        android:layout_marginTop="5dp"
        android:background="@drawable/design_red_point"
        android:gravity="center"
        android:textSize="@dimen/text_size_comment_20"
        android:text="7"
        android:textColor="@android:color/white" />

Android中Textview显示带图片html

2015年10月5日

Textview显示“img”标签,大家都会想到就是构建ImageGetter,重载一下其 public Drawable getDrawable(String source)方法,获取该路径的图片。
例如:

final Html.ImageGetter imageGetter = new Html.ImageGetter() {
        public Drawable getDrawable(String source) {
            return drawable;
        };

    };

下面来说下public Drawable getDrawable(String source)这个方法,source就是图片路径!
例如:

final String sText = "测试图片信息:<br><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" /><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" />";
tView.setText(Html.fromHtml(sText, imageGetter, null));

则source就是img的src的值,既是:http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg这个图片路径

当然这个 这个路径既可以是网络图片,也可以本地图片,项目资源图片

例如:本地图片<img src=\""/sdcard/images/test.jpg"\"/>   项目资源图片 <img src=\""+R.drawable.market_none_image+"\"/>
但是不同的路径,ImageGetter的重载处理方法都不一样,下面来一一介绍各种的处理方式.

第一种:本地图片

final String sText2 = "测试图片信息:<img src=\"/mnt/sdcard/temp/1.jpg\" />";
tView.setText(Html.fromHtml(sText2, imageGetter, null));

final Html.ImageGetter imageGetter = new Html.ImageGetter() {

    public Drawable getDrawable(String source) {
        Drawable drawable=null;
    drawable=Drawable.createFromPath(source);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    return drawable;  };
}

第二种:项目资源图片

final String sText1 = "测试图片信息:<img src=\""+R.drawable.market_none_image+"\" />";tView.setText(Html.fromHtml(sText1, imageGetter, null));

final Html.ImageGetter imageGetter = new Html.ImageGetter() {

    public Drawable getDrawable(String source) {
        Drawable drawable=null;
    int rId=Integer.parseInt(source);
    drawable=getResources().getDrawable(rId);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    return drawable;    };
}

第三种:网络图片

final String sText = "测试图片信息:<br><img src=\"http://pic004.cnblogs.com/news/201211/20121108_091749_1.jpg\" />";
tView.setText(Html.fromHtml(sText, imageGetter, null));

final Html.ImageGetter imageGetter = new Html.ImageGetter() {

    public Drawable getDrawable(String source) {
        Drawable drawable=null;
    URL url;
    try {
        url = new URL(source);
        drawable = Drawable.createFromStream(url.openStream(), "");
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());            
    return drawable;     };
}

通过这三个方式,可以看出,不同的图片路径,得到图片的处理方式不同,大家也能一目了然的看出来ImageGetter是干什么的了,就是得到img中src所需的图片!

提醒一点:获取图片以后,一定要设置图片的边界,界线,即:drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());,不然获取图片后,Textview不能显示图片。

通过以上三种方式,是能可以显示出来图片,但是我发现了一个问题,就是第三种,显示网络图片,我用android2.3的系统,可以显示图片出来,并且如果图片比较大,应用会卡的现象,肯定是因为使用主线程去获取网络图片造成的,但如果我用android4.0以上的系统运行,则不能显示图片,只显示小方框。

究其原因,是在4.0的系统上执行的时候报错了,异常是:android.os.NetworkOnMainThreadException 经过查文档,原来是4.0系统不允许主线程(UI线程)访问网络,因此导致了其异常。说白了就是在主线程上访问网络,会造成主线程挂起,系统不允许使用了。

androidannotations出现生成的类 “错误: 找不到符号”

2015年10月4日

使用androidannotations框架注解的Android出现全部注解生成类出现“错误: 找不到符号”提示。这个错误确实有点吓人,因为提示太含糊了。

错误: 找不到符号
import net.unix8.program.user.UserDetailActivity_;

错误的原因,是我的代码中有这么一条注解

    @ViewById
    FloatingActionButton mAddButton;

然而在我的xml中的FloatingActionButton的id并不是mAddButton,因此改过来名字就行了。

    <com.melnykov.fab.FloatingActionButton
        android:id="@+id/mAddButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center|right"
        android:layout_marginRight="16dp"
        android:src="@drawable/ticket_buy"
        fab:fab_colorNormal="@color/colorPrimary"
        fab:fab_colorPressed="@color/colorPrimaryLight" />

解决Android Studio添加依赖时出现“Manifest merger failed”

2015年10月4日

今天一技术群里的朋友碰到个问题,说用Android Studio导入第三方依赖库时报错,出现这个:

报错1

所导入的依赖为这个

SweetAlertDialog:
https://github.com/pedant/sweet-alert-dialog

于是多管闲事的我试着导入了下,也出错了,不过没出现上面截图的错误,而出现Manifest merger failed(Manifest合并失败)错误,如下图:

报错2

1
2
3
4
5
Error:(7, 9) Attribute application@icon value=(@mipmap/ic_launcher) from AndroidManifest.xml:7:9
Error:(7, 9) Execution failed for task ':importdemo:processDebugManifest'.
> Manifest merger failed : Attribute application@icon value=(@mipmap/ic_launcher) from AndroidManifest.xml:7:9
    is also present at com.pnikosis:materialish-progress:1.0:13:9 value=(@drawable/ic_launcher)
	Suggestion: add 'tools:replace="android:icon"' to <application> element at AndroidManifest.xml:5:5 to override

分析错误

分析错误提示,

  1. 主程序module清单文件中,application节点的android:icon属性引用了@mipmap/ic_launcher图片资源,
  2. 而依赖module的清单文件中,同样的android:icon属性却引用了@drawable/ic_launcher这个图片资源,

两个属性值产生冲突,导致合并清单文件失败。

虽然知道错误是什么,但是仍然不知道咋解决啊。
其实英语没那么糟糕,细心点的话,就能看到错误提示中就给出了解决问题的建议。

Suggestion: add ‘tools:replace=”android:icon”‘ to element at AndroidManifest.xml:5:5 to override

意思在AndroidManifest.xml文件的<application>节点中添加tools:replace="android:icon"属性。

修改

按提示进行修改,再同步Gradle,问题解决。

tools:replace 属性的作用可以在这个页面找到(需要搭梯)
http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger
在页面搜索 Override an attribute coming from a library 即可定位到。

APP设计师必上的10个APP图标素材资源站

2015年10月3日

1、最大的扁平化图标素材库-Flaticon
目前Flaticon收集了 54087 多个响应式的扁平化图标,在 Flaticon酷站上,我们可以很快搜索找到自己想要的图标,也可以通过分类,最受欢迎,或者其他标签方式找到自己想要的图标。
并且每组图标,都有 Webfont,SVG,PNG 等三种格式,如果下载 PNG 格式的图标的话,还可以选择 16px,24px,一直到 512 px 等各种大小,非常方便。
只要我们输入英文关键词的搜索即可列出很多我们想要的移动APP图标素材。
APP图标素材资源站网址:www.Flaticon.com
推荐指数:★★★★★

2、IconPng.com 爱看图标网,免费中文图标搜索引擎
收录了76812个免费的PPT图标ICON素材及网页设计图标资源,具有按分类、色系、标题、系列搜索图标的功能,帮助您以最快的速度找到喜欢的APP图标ICONS。支持中文搜索,非常方便至极!
http://www.iconpng.com/
推荐指数:★★★★★

3、icomoon.io/app/ 非常强悍的图标字体生成利器。
Icomoon.io:矢量图标素材分享网是一个提供一系列的矢量图标素材的博客站点,还有免费的HTML5应用程序的自定义图标字体。
使用icomoon您可以轻松地搜索和下载矢量图标或生成的字体(图标字体)。
酷站网址:http://icomoon.io/app/
推荐指数:★★★★★

4、阿里巴巴矢量图标库-iconfont
Iconfont-中国第一个最大且功能最全的矢量图标库,提供矢量图标下载、在线存储、格式转换等功能。阿里巴巴体验团队倾力打造,设计和前端开发的便捷工具。是中国国内非常棒的移动APP图标资源库。
扩展阅读:5个免费设计英文字体酷站推荐
酷站网址:http://www.iconfont.cn/
推荐指数:★★★★★

5、EASYICON 中文图标搜索引擎!可批量下载PNG、ICO、ICNS等格式图标
EasyIcon:免费图标搜索下载网是国内一个免费的图标搜索下载站点,可通过关键词和推荐来寻找合适的素材,同时支持打包下载功能。提供超过四十六万个PNG、ICO、ICNS格式图标搜索、图标下载服务。也是国内非常受设计师欢迎的移动APP图标素材资源站。
酷站网址:http://www.easyicon.net/
推荐指数:★★★★★

6、IconMonstr:免费简约素材图标下载站
IconMonstr:免费简约素材图标下载站是一个提供免费的PNG/SVG格式的素材下载站点,简介的界面收录了海量的黑白图标素材,用户可以搜索查找,所有素材都可以免费下载。
推荐2个移动App矢量图标库-iconmonstr和NounProject
iconmonstr酷站官网:http://iconmonstr.com/
推荐指数:★★★★★

7、国外扁平化APP图标素材站推荐:iconsDB
iconsDB.com是一个超棒的免费图标库网站。目前拥有2314个图标,你可以自定义颜色和尺寸并且下载,下载次数高达1,679,043。所有的图标都可以免费在个人或者商用项目中使用。
酷站网址:http://www.iconsdb.com/
推荐指数:★★★★★

8、icons8 免费的icon packs for windows 8, ios 7 and android
icon8.com是全球最大的icon packs for windows 8, ios 7 and android图标素材库。icon8.com收集或创造的图标数量已经超过5200个啦!而且分类非常规范和整齐。
同时提供icon8网站的APP下载。该APP可以直接预览不同的图标,在移动端查找图标很方便。
酷站网址:http://www.icon8.com/
推荐指数:★★★★★

9、iconfinder 强大的iconAPP图标素材搜索站点
Iconfinder:在线图标搜索引擎是一个专注于图标的搜索引擎,通过它你可以快速找到你所需要的图标,并且它收录的图标一般都是免费的,所找到的图标素材都是可以免费下载。
酷站网址:www.iconfinder.com/
推荐指数:★★★★★

10、modernuiicons-国外优秀的扁平化APP图标素材库
Modern UI Icons (也叫Windows Phone Icon Pack) 是一组750多个非常漂亮的设计图标。这些图标主要用于Windows Phone 和 Windows 8 开发,但也可以用于其它移动APP和Web应用上。值得设计师们来收藏!
1246个扁平化的图标。适合winphone和安卓上面的图标。
酷站网址:modernuiicons.com/
推荐指数:★★★★★