Android 使用ViewPager实现类似gallery画廊的效果(画廊效果之ViewPager显示多个图片)

这个画廊的效果利用到了View的clipChildren属性,我们在这里要把ViewPager以及它的父窗体都设置为false,如下: Android:clipChildren=”false” 因为如果clipChildren属性设置为true,就表明我们要将children给clip掉,就是说对于子元素来说,超出当前view的部分都会被切掉,那我们在这里把它设置成false,就表明超出view的部分,不要切掉,依然显示。 xml代码部分: <LinearLayout android:id=”@+id/container” android:layout_width=”match_parent” android:layout_height=”100dp” android:clipChildren=”false” android:gravity=”center_horizontal” android:layerType=”software” android:orientation=”horizontal” > <android.support.v4.view.ViewPager android:id=”@+id/viewpager” android:layout_width=”match_parent” android:layout_height=”match_parent” android:layout_marginLeft=”110dp” android:layout_marginRight=”110dp” android:clipChildren=”false” > </android.support.v4.view.ViewPager> Java代码部分: // 1.设置幕后item的缓存数目 mViewPager.setOffscreenPageLimit(3); // 2.设置页与页之间的间距 mViewPager.setPageMargin(10); // 3.将父类的touch事件分发至viewPgaer,否则只能滑动中间的一个view对象 container.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return mViewPager.dispatchTouchEvent(event); } }); 参考效果图(上面代码并不能实现效果图,仅供参考): 正常情况下, ViewPager 一页只能显示一项数据, 但是如果需求是, 除了小显示本页数据, 还有包 左右两半的数据 也都露出一点来呢? 这该怎么处理? 后面在网上了搜了一下, 发现有不少这样得到文章, 这里自己也写一篇总结一下. 其实 主要就是用到 View 的 android:clipChildren 属性. 简单来说这个属性, 就是 父View 是否 束缚 子View 的显示范围. 如果 父View 有 padding , 那么 子View 则在 padding区域是不能显示内容的, 但是如果 设置 android:clipChildren 为 false 时, 则子View 就可以在 父View 的padding屈戌显示内容了. ok 基本了解了 android:clipChildren 那么来处理一下 ViewPager吧 先看一下我做的demo: ...

2017年8月29日 · 2 分钟 · 天边的星星

Android ToolBar 使用完全解析

ToolBar简介 ToolBar是Android 5.0推出的一个新的导航控件用于取代之前的ActionBar,由于其高度的可定制性、灵活性、具有Material Design风格等优点,越来越多的应用也用上了ToolBar,比如常用的知乎软件其顶部导航栏正是使用ToolBar。官方考虑到仍有一部分用户的手机版本号低于5.0,所以,ToolBar也放进了support v7包内,使得低版本的系统也能使用上ToolBar。本文将使用support v7支持包的ToolBar来进行讲解,包括其基本用法、样式定制等知识点。 ToolBar的基本使用 引入support v7支持包 在你项目的build.gradle内输入如下代码,即能引入支持包,该支持包内有能向下兼容的ToolBar: `dependencies { compile fileTree(dir: &lt;span class="hljs-string">'libs'&lt;/span>, include: [&lt;span class="hljs-string">'*.jar'&lt;/span>]) compile &lt;span class="hljs-string">'com.android.support:appcompat-v7:23.1.1'&lt;/span> }`<a target="_blank" name="t3"></a> 更改主题 为了能够正常使用ToolBar,我们需要隐藏原来的ActionBar,这个可以在主题中修改,在values/styles.xml中做出如下修改: " width="20" data-original-code="![]( data-wp-preserve=)1 2 1 2 " data-snippet-id="ext.2bc0da59d9ff7d2cc4639972565d3679" data-snippet-saved="false" data-codota-status="done" style="white-space: nowrap; word-wrap: break-word; box-sizing: border-box; position: relative; overflow-y: hidden; overflow-x: auto; margin: 0px 0px 1.1em; font-family: "Source Code Pro", monospace; display: block; padding: 5px 5px 5px 60px; font-size: 14px; line-height: 1.45; word-break: break-all; color: rgb(51, 51, 51); background-color: rgba(128, 128, 128, 0.05); border: 0px solid rgb(136, 136, 136); border-radius: 0px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"&gt;`&lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">style&lt;/span> &lt;span class="hljs-attribute">name&lt;/span>=&lt;span class="hljs-value">"AppTheme"&lt;/span> &lt;span class="hljs-attribute">parent&lt;/span>=&lt;span class="hljs-value">"Theme.AppCompat.Light.NoActionBar"&lt;/span>&gt;&lt;/span> &lt;span class="hljs-tag">&lt;/&lt;span class="hljs-title">style&lt;/span>&gt;&lt;/span>` 继承了Theme.Appcompat.Light.NoActionBar主题,这里提一下,这个Theme.AppCompat是支持包内的主题,对应着5.0版本的Theme.Material主题。然后在manifest文件中引用这个主题。 ...

2017年8月26日 · 6 分钟 · 天边的星星

新布局节点ConstraintLayout基本使用

Android ConstraintLayout详解 AndroidStudio2.2开始,就推出了一个牛逼的布局,ConstraintLayout,此布局像是一个升级版的RelativeLayout,但是功能比RelativeLayout强大许多,号称一层布局就可以搞定复杂页面。在AS2.2下还可以用拖拽控件的方式就行布局(设计师的福音),不过本篇不讲解拖拽控件的相关用法,主要讲解一些相关属性含义。 想学习拖拽控件设计ConstraintLayout的请点这里。 Android官方教程在此。 本文讲解参考这里,需自备梯子。 开始! 相对位置这个相对位置的设置有点类似RelativeLayout的layout_toLeftOf、alignParentLeft等这些属性。 ConstraintLayout一共支持相对位置的属性在此: layout_constraintLeft_toLeftOf layout_constraintLeft_toRightOf layout_constraintRight_toLeftOf layout_constraintRight_toRightOf layout_constraintTop_toTopOf layout_constraintTop_toBottomOf layout_constraintBottom_toTopOf layout_constraintBottom_toBottomOf layout_constraintBaseline_toBaselineOf layout_constraintStart_toEndOf layout_constraintStart_toStartOf layout_constraintEnd_toStartOf layout_constraintEnd_toEndOf拿第一个属性来说,layout_constraintLeft_toLeftOf=”@+id/id_first”,表示当前View的左边界与id_first的View的做边界对齐。其实这个属性翻译成中文就是:当前view的左边对齐与引用view的左边。 例子: <Button android:id=&quot;@+id/buttonB&quot; ... app:layout_constraintLeft_toRightOf=&quot;@+id/buttonA&quot; />1 2 3 1 2 3 1 2 3 1 2 3 " data-snippet-id="ext.3190b6ad748f0e96e5cbd62a084f67f5" data-snippet-saved="false" data-codota-status="done">`&lt;Button android:id=&lt;span class="hljs-string">"@+id/buttonA"&lt;/span> &lt;span class="hljs-keyword">...&lt;/span> /&gt; &lt;Button android:id=&lt;span class="hljs-string">"@+id/buttonB"&lt;/span> &lt;span class="hljs-keyword">...&lt;/span> app:layout_constraintLeft_toRightOf=&lt;span class="hljs-string">"@+id/buttonA"&lt;/span> /&gt;` 效果如下: 当然,这些属性也支持设置为对齐父布局的左右前后。 1 2 1 2 1 2 1 2 " data-snippet-id="ext.66574d68fbfbe560220fafc526a7805f" data-snippet-saved="false" data-codota-status="done">`&lt;Button android:id=&lt;span class="hljs-string">"@+id/buttonB"&lt;/span> &lt;span class="hljs-keyword">...&lt;/span> app:layout_constraintLeft_toLeftOf=&lt;span class="hljs-string">"parent"&lt;/span> /&gt;` 这样,buttonB就依附在父布局的左边。类似Realitelayout的alignParentLeft。 margin属性这个属性没啥好说的,跟其他布局的margin属性差不多。支持的属性如下: Android:layout_marginStart android:layout_marginEnd android:layout_marginLeft android:layout_marginTop android:layout_marginRight android:layout_marginBottom 注意:如上图,假如A紧贴父布局的左侧,B距离A 100dp,A设置为gone后,则B距离父布局的左侧100dp。 goneMargin属性这个布局比较有意思,还是拿上面的那副图做示例,假设我们现在有这样一个需求:假设A设置为gone,后,B需要距离父布局的左侧200dp,怎么办?这时候,goneMargin属性就派上用场啦,只要设置B的layout_goneMarginLeft=200dp即可。这样,A不为gone的时候,B距离A 100dp,A为gone时,B距离父布局左侧200dp。 一共支持的属性如下: layout_goneMarginStart layout_goneMarginEnd layout_goneMarginLeft layout_goneMarginTop layout_goneMarginRight layout_goneMarginBottom Centering positioning and bias ,设置居中或者按比例偏移。 假设我们要设置一个控件居中怎么办?很简单,利用上面介绍过的属性就可以办到。 <Button android:id=&quot;@+id/button&quot; ... app:layout_constraintHorizontal_bias=&quot;0.3&quot; app:layout_constraintLeft_toLeftOf=&quot;parent&quot; app:layout_constraintRight_toRightOf=&quot;parent/> </>1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 " data-snippet-id="ext.fa91acc62f5d2da7b193dcfae6657c0a" data-snippet-saved="false" data-codota-status="done">` &lt;android.support.constraint.ConstraintLayout &lt;span class="hljs-keyword">...&lt;/span>&gt; &lt;Button android:id=&lt;span class="hljs-string">"@+id/button"&lt;/span> &lt;span class="hljs-keyword">...&lt;/span> app:layout_constraintHorizontal_bias=&lt;span class="hljs-string">"0.3"&lt;/span> app:layout_constraintLeft_toLeftOf=&lt;span class="hljs-string">"parent"&lt;/span> app:layout_constraintRight_toRightOf=&lt;span class="hljs-string">"parent/&gt; &lt;/&gt;&lt;/span>` bias支持的属性如下: layout_constraintHorizontal_bias layout_constraintVertical_bias ...

2017年6月29日 · 3 分钟 · 天边的星星

Android RecyclerView 使用完全解析 体验艺术般的控件

概述 RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。 据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView、GridView。 那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。 你想要控制其显示的方式,请通过布局管理器LayoutManager 你想要控制Item间的间隔(可绘制),请通过ItemDecoration 你想要控制Item增删的动画,请通过ItemAnimator 你想要控制点击、长按事件,请自己写(擦,这点尼玛。) 基本使用 鉴于我们对于ListView的使用特别的熟悉,对比下RecyclerView的使用代码: `mRecyclerView = findView(R.id.id_recyclerview); &lt;span class="hljs-comment">//设置布局管理器&lt;/span> mRecyclerView.setLayoutManager(layout); &lt;span class="hljs-comment">//设置adapter&lt;/span> mRecyclerView.setAdapter(adapter) &lt;span class="hljs-comment">//设置Item增加、移除动画&lt;/span> mRecyclerView.setItemAnimator(&lt;span class="hljs-keyword">new&lt;/span> DefaultItemAnimator()); &lt;span class="hljs-comment">//添加分割线&lt;/span> mRecyclerView.addItemDecoration(&lt;span class="hljs-keyword">new&lt;/span> DividerItemDecoration( getActivity(), DividerItemDecoration.HORIZONTAL_LIST));` ok,相比较于ListView的代码,ListView可能只需要去设置一个adapter就能正常使用了。而RecyclerView基本需要上面一系列的步骤,那么为什么会添加这么多的步骤呢? 那么就必须解释下RecyclerView的这个名字了,从它类名上看,RecyclerView代表的意义是,我只管Recycler View,也就是说RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)。 Just like ListView Activity `&lt;span class="hljs-keyword">package&lt;/span> com.zhy.sample.demo_recyclerview; &lt;span class="hljs-keyword">import&lt;/span> java.util.ArrayList; &lt;span class="hljs-keyword">import&lt;/span> java.util.List; &lt;span class="hljs-keyword">import&lt;/span> android.os.Bundle; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.app.ActionBarActivity; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.widget.LinearLayoutManager; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.widget.RecyclerView; &lt;span class="hljs-keyword">import&lt;/span> android.support.v7.widget.RecyclerView.ViewHolder; &lt;span class="hljs-keyword">import&lt;/span> android.view.LayoutInflater; &lt;span class="hljs-keyword">import&lt;/span> android.view.View; &lt;span class="hljs-keyword">import&lt;/span> android.view.ViewGroup; &lt;span class="hljs-keyword">import&lt;/span> android.widget.TextView; &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-class">&lt;span class="hljs-keyword">class&lt;/span> &lt;span class="hljs-title">HomeActivity&lt;/span> &lt;span class="hljs-keyword">extends&lt;/span> &lt;span class="hljs-title">ActionBarActivity&lt;/span> {&lt;/span> &lt;span class="hljs-keyword">private&lt;/span> RecyclerView mRecyclerView; &lt;span class="hljs-keyword">private&lt;/span> List&lt;String&gt; mDatas; &lt;span class="hljs-keyword">private&lt;/span> HomeAdapter mAdapter; &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">protected&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">onCreate&lt;/span>(Bundle savedInstanceState) { &lt;span class="hljs-keyword">super&lt;/span>.onCreate(savedInstanceState); setContentView(R.layout.activity_single_recyclerview); initData(); mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); mRecyclerView.setLayoutManager(&lt;span class="hljs-keyword">new&lt;/span> LinearLayoutManager(&lt;span class="hljs-keyword">this&lt;/span>)); mRecyclerView.setAdapter(mAdapter = &lt;span class="hljs-keyword">new&lt;/span> HomeAdapter()); } &lt;span class="hljs-keyword">protected&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">initData&lt;/span>() { mDatas = &lt;span class="hljs-keyword">new&lt;/span> ArrayList&lt;String&gt;(); &lt;span class="hljs-keyword">for&lt;/span> (&lt;span class="hljs-keyword">int&lt;/span> i = &lt;span class="hljs-string">'A'&lt;/span>; i &lt; &lt;span class="hljs-string">'z'&lt;/span>; i++) { mDatas.add(&lt;span class="hljs-string">""&lt;/span> + (&lt;span class="hljs-keyword">char&lt;/span>) i); } } class HomeAdapter extends RecyclerView.Adapter&lt;HomeAdapter.MyViewHolder&gt; { &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">public&lt;/span> MyViewHolder &lt;span class="hljs-title">onCreateViewHolder&lt;/span>(ViewGroup parent, &lt;span class="hljs-keyword">int&lt;/span> viewType) { MyViewHolder holder = &lt;span class="hljs-keyword">new&lt;/span> MyViewHolder(LayoutInflater.from( HomeActivity.&lt;span class="hljs-keyword">this&lt;/span>).inflate(R.layout.item_home, parent, &lt;span class="hljs-keyword">false&lt;/span>)); &lt;span class="hljs-keyword">return&lt;/span> holder; } &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">onBindViewHolder&lt;/span>(MyViewHolder holder, &lt;span class="hljs-keyword">int&lt;/span> position) { holder.tv.setText(mDatas.get(position)); } &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-keyword">int&lt;/span> &lt;span class="hljs-title">getItemCount&lt;/span>() { &lt;span class="hljs-keyword">return&lt;/span> mDatas.size(); } class MyViewHolder extends ViewHolder { TextView tv; &lt;span class="hljs-keyword">public&lt;/span> &lt;span class="hljs-title">MyViewHolder&lt;/span>(View view) { &lt;span class="hljs-keyword">super&lt;/span>(view); tv = (TextView) view.findViewById(R.id.id_num); } } } }` Activity的布局文件 `&lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">RelativeLayout&lt;/span> &lt;span class="hljs-attribute">xmlns:android&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/apk/res/android"&lt;/span> &lt;span class="hljs-attribute">xmlns:tools&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/tools"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">android.support.v7.widget.RecyclerView &lt;/span> &lt;span class="hljs-attribute">android:id&lt;/span>=&lt;span class="hljs-value">"@+id/id_recyclerview"&lt;/span> &lt;span class="hljs-attribute">android:divider&lt;/span>=&lt;span class="hljs-value">"#ffff0000"&lt;/span> &lt;span class="hljs-attribute">android:dividerHeight&lt;/span>=&lt;span class="hljs-value">"10dp"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> /&gt;&lt;/span> &lt;span class="hljs-tag">&lt;/&lt;span class="hljs-title">RelativeLayout&lt;/span>&gt;&lt;/span>` Item的布局文件 `&lt;span class="hljs-pi">&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">FrameLayout&lt;/span> &lt;span class="hljs-attribute">xmlns:android&lt;/span>=&lt;span class="hljs-value">"http://schemas.android.com/apk/res/android"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:background&lt;/span>=&lt;span class="hljs-value">"#44ff0000"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"wrap_content"&lt;/span> &gt;&lt;/span> &lt;span class="hljs-tag">&lt;&lt;span class="hljs-title">TextView &lt;/span> &lt;span class="hljs-attribute">android:id&lt;/span>=&lt;span class="hljs-value">"@+id/id_num"&lt;/span> &lt;span class="hljs-attribute">android:layout_width&lt;/span>=&lt;span class="hljs-value">"match_parent"&lt;/span> &lt;span class="hljs-attribute">android:layout_height&lt;/span>=&lt;span class="hljs-value">"50dp"&lt;/span> &lt;span class="hljs-attribute">android:gravity&lt;/span>=&lt;span class="hljs-value">"center"&lt;/span> &lt;span class="hljs-attribute">android:text&lt;/span>=&lt;span class="hljs-value">"1"&lt;/span> /&gt;&lt;/span> &lt;span class="hljs-tag">&lt;/&lt;span class="hljs-title">FrameLayout&lt;/span>&gt;&lt;/span>` 这么看起来用法与ListView的代码基本一致哈~~ 看下效果图: ...

2017年6月20日 · 15 分钟 · 天边的星星

Android开发中Gradle配置使用

Android开发中Gradle配置使用 前言 每次创建私有项目都需要配置gradle文件,没什么技术含量,还要多劳动(程序员就是懒),为了能方便使用,才有了本仓库的诞生。 欢迎各位小伙伴们来砸场,喜欢请star下… 私有仓库使用 在下载config.properties文件放到工厂根目录(和gradle.properties同级) 如果使用Artifactory仓库配置工程build.gradle文件请看详细文件 在项目build.gradle文件中使用 apply from:&#39;https://coding.net/u/zdl_411437734/p/gradle/git/raw/master/nexusBintry.gradle&#39; 或者 apply from:&#39;https://coding.net/u/zdl_411437734/p/gradle/git/raw/master/artifactBintry.gradle&#39; 执行相关命令即可 gradle uploadArchives (nexus仓库) 或者 gradle assembleRelease artifactoryPublish (artifactory仓库) 详细使用文档 Sonarqube使用 详细使用文档 pack(打包)使用 经常打包apk,有一个困扰,怎么修改打包后的名称,怎么区分打包的是release版本还是debug版本,想了解请继续看 在项目的buil.gradle文件配置打包的版本和输出的名称 //打包APK根据不同的环境打包不同的名称 ext{ productName = project.name versionName = "1.0.1" } //productName 打包出来的名称 //versionName 打包显示版本号 2 . 引入packe.gradle文件下载packe.gradle apply from:"./pack.gradle" 或者 apply from:"https://coding.net/u/zdl_411437734/p/gradle/git/raw/master/pack.gradle" 3 . 打包即可(~~) sign(签名)使用 有时候,在集成第三方时候,需要我们输入签名,在开发中和发布中一般默认都是2个keystroe,在这种情况下,开发很不方便,不断要打包成正式包才能测试,为了解决这个问题,我们配置gradle在开发时就使用正式签名开发,想了解请继续看 在项目的buil.gradle文件配置打包的版本和输出的名称 //打包APK根据不同的环境打包不同的名称 ext{ productName = "CommonProject" versionName = "2.0.1" keyPassword = "android" keyFilePath = "/Users/jason/Documents/keystore/android.keystore" storePassword = "android" keyAlias = "android" } //productName 打包出来的名称 //versionName 打包显示版本号 //keyPassword 密码 //keyFilePath 正式全路径 //storePassword 密码 //keyAlias 别名 2 . 引入sign.gradle文件下载sign.gradle ...

2017年6月7日 · 1 分钟 · 天边的星星

自定义ImageView 宽度自适应屏幕,高度等比缩放

实现方法很简单,根据图片文件的宽度与ImageView的宽度比例关系算出ImageView的高度。 package com.etongwl.commonlibs.view; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.util.AttributeSet; import android.view.ViewGroup; import android.widget.ImageView; /* * @Override public void setImageDrawable(final Drawable drawable) { super.setImageDrawable(drawable); if (drawable != null) { post(new Runnable() { @Override public void run() { float mWidth = getWidth(); float pWidth = drawable.getBounds().width(); float pHeight = drawable.getBounds().height(); int mHeight = (int) ((mWidth / pWidth) * pHeight); LayoutParams params = getLayoutParams(); params.height = mHeight; params.width = (int) mWidth; setLayoutParams(params); } }); } } 首先, 如果drawable不为空, 则通过drawable.getBounds()去获取drawable边界的宽和高. 在根据ImageView的宽与drawable的宽的比例去计算高度, 最后通过LayoutParams设置ImageView的高度 * */ /* &lt;com.etongwl.commonlibs.view.AdaptiveImageView android:id="@+id/detail_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="15dp" android:scaleType="centerCrop" android:background="@drawable/diandianxinwen" android:visibility="visible" /&gt; */ /** * 按比例缩放 */ @SuppressLint("AppCompatCustomView") public class AdaptiveImageView extends ImageView { // 控件默认长、宽 private int defaultWidth = 0; private int defaultHeight = 0; // 比例 private float scale = 0; public AdaptiveImageView(Context context) { super(context); } public AdaptiveImageView(Context context, AttributeSet attrs) { super(context, attrs); } public AdaptiveImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable == null) { return; } if (getWidth() == 0 || getHeight() == 0) { return; } this.measure(0, 0); if (drawable.getClass() == NinePatchDrawable.class) return; Bitmap b = ((BitmapDrawable) drawable).getBitmap(); Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); if (bitmap.getWidth() == 0 || bitmap.getHeight() == 0) { return; } if (defaultWidth == 0) { defaultWidth = getWidth(); } if (defaultHeight == 0) { defaultHeight = getHeight(); } scale = (float) defaultWidth / (float) bitmap.getWidth(); defaultHeight = Math.round(bitmap.getHeight() * scale); ViewGroup.LayoutParams params = this.getLayoutParams(); params.width = defaultWidth; params.height = defaultHeight; this.setLayoutParams(params); super.onDraw(canvas); } } 简单实现ImageView宽度填满屏幕,高度自适应的两种方式 两种方式 1.重写View的onMeasure方法参考这里easion_zms的专栏 核心代码 ...

2017年5月2日 · 4 分钟 · 天边的星星

Android 中的CreatePackageContext()

/** * Return a new Context object for the given application name. This * Context is the same as what the named application gets when it is * launched, containing the same resources and class loader. Each call to * this method returns a new instance of a Context object; Context objects * are not shared, however they share common state (Resources, ClassLoader, * etc) so the Context instance itself is fairly lightweight. ...

2017年4月25日 · 3 分钟 · 天边的星星

Android动态加载基础 ClassLoader工作机制

类加载器ClassLoader 早期使用过Eclipse等Java编写的软件的同学可能比较熟悉,Eclipse可以加载许多第三方的插件(或者叫扩展),这就是动态加载。这些插件大多是一些Jar包,而使用插件其实就是动态加载Jar包里的Class进行工作。这其实非常好理解,Java代码都是写在Class里面的,程序运行在虚拟机上时,虚拟机需要把需要的Class加载进来才能创建实例对象并工作,而完成这一个加载工作的角色就是ClassLoader。 对于Java程序来说,编写程序就是编写类,运行程序也就是运行类(编译得到的class文件),其中起到关键作用的就是类加载器ClassLoader。 Android的Dalvik/ART虚拟机如同标准JAVA的JVM虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。因此,我们可以利用这一点,在程序运行时手动加载Class,从而达到代码动态加载可执行文件的目的。Android的Dalvik/ART虚拟机虽然与标准Java的JVM虚拟机不一样,ClassLoader具体的加载细节不一样,但是工作机制是类似的,也就是说在Android中同样可以采用类似的动态加载插件的功能,只是在Android应用中动态加载一个插件的工作要比Eclipse加载一个插件复杂许多(这点后面在解释说明)。 有几个ClassLoader实例? 动态加载的基础是ClassLoader,从名字也可以看出,ClassLoader就是专门用来处理类加载工作的,所以这货也叫类加载器,而且一个运行中的APP 不仅只有一个类加载器。 其实,在Android系统启动的时候会创建一个Boot类型的ClassLoader实例,用于加载一些系统Framework层级需要的类,我们的Android应用里也需要用到一些系统的类,所以APP启动的时候也会把这个Boot类型的ClassLoader传进来。 此外,APP也有自己的类,这些类保存在APK的dex文件里面,所以APP启动的时候,也会创建一个自己的ClassLoader实例,用于加载自己dex文件中的类。下面我们在项目里验证看看 ` &lt;span class="hljs-annotation">@Override&lt;/span> &lt;span class="hljs-function">&lt;span class="hljs-keyword">protected&lt;/span> &lt;span class="hljs-keyword">void&lt;/span> &lt;span class="hljs-title">onCreate&lt;/span>&lt;span class="hljs-params">(Bundle savedInstanceState)&lt;/span> &lt;/span>{ &lt;span class="hljs-keyword">super&lt;/span>.onCreate(savedInstanceState); ClassLoader classLoader = getClassLoader(); &lt;span class="hljs-keyword">if&lt;/span> (classLoader != &lt;span class="hljs-keyword">null&lt;/span>){ Log.i(TAG, &lt;span class="hljs-string">"[onCreate] classLoader "&lt;/span> + i + &lt;span class="hljs-string">" : "&lt;/span> + classLoader.toString()); &lt;span class="hljs-keyword">while&lt;/span> (classLoader.getParent()!=&lt;span class="hljs-keyword">null&lt;/span>){ classLoader = classLoader.getParent(); Log.i(TAG,&lt;span class="hljs-string">"[onCreate] classLoader "&lt;/span> + i + &lt;span class="hljs-string">" : "&lt;/span> + classLoader.toString()); } } }` 输出结果为 ...

2017年4月25日 · 7 分钟 · 天边的星星

使用Artifactory搭建本地maven仓库

引言 前段日子,公司为了提高产品出产效率,想把公司每个产品各个小功能抽取出来,这样再做一个新产品的时候,重复的功能就可以直接使用之前写好的模块就行了。想法是不错的,但一开始实践起来很麻烦,同事A就将自己的模块做成module,为了图方便,将整个module项目直接发送给同事B和同事C,代码第一次写成以后一般都会有一些小bug的,这样,同事A在自己电脑上修改代码,然后再次修改代码分别传给B和C。B和C需要替换之前的module,重新运行。这相当的麻烦,如果还有同事D,E,F..做起来真是噩梦,可能有有人想问,为什么不用svn或者git,用版本控制工具当然会好非常多,但每次pull其实也比较麻烦。还有另一种方法,使用本地maven仓库,使用过android studio的开发者都应该体会过其中的好处,当需要依赖一个新的模块(或者叫library)时,只需要这样 填写需要的模块及对应的版本号,同步一下就行了,很方便。本篇文章就教各位如何使用Artifactory来搭建本地仓库,来完成上图的效果 什么是Artifactory? 一句话,开源的Maven仓库管理者 搭建Artifactory 1.检测你的jdk版本是否为1.8及以上 打开cmd,输入java -version,如果输出结果如下所示即可,如果是1.6或者1.7,去官网下载最新版本替换 `java -version java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)" data-snippet-id="ext.437a4825669d574acb250e72155a8b81" data-snippet-saved="false" data-codota-status="done">C:\Users\Administrator>java -version<br /> java version "1.8.0_31"<br /> Java(TM) SE Runtime Environment (build 1.8.0_31-b13)<br /> Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)` 2.下载Artifactory,解压下载好的安装包,打开解压后文件夹下的bin文件夹,运行artifactory.bat,大概等待1分钟左右就安装完成了 3.打开http://localhost:8081/artifactory将会看到管理界面,如果看到此界面,就表示artifactory已经安装成功了.如果不是该界面,则需要等待安装完成 上传library到maven 创建自己的library project(注意你的 module是apply plugin: ‘com.android.library’),写好自己模块的代码后,准备上传 1.添加相关插件引用 在你library 项目中顶级的build.gradle文件中,添加一条新的classpath引用 **[plain]** [view plain](http://blog.csdn.net/level_26/article/details/53483444#)<span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/level_26/article/details/53483444#)</span> <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="16" height="16" align="middle" name="ZeroClipboardMovie_1" data-mce-fragment="1"> </embed> </div> </div> - <span style=&#8221;font-family:Microsoft YaHei;font-size:14px;&#8221;>buildscript { - dependencies { - classpath &#8220;org.jfrog.buildinfo:build-info-extractor-gradle:4.4.0&#8221; - } - }</span> 然后在你的library module的build.gradle中,添加两条语句 ...

2017年3月21日 · 3 分钟 · 天边的星星

AndroidStudio 多层级 Module 对 aar 引用

问题:有个arr文件被放到Module A中引用,现在Module B又依赖了Module A,则在编译过程中会发生错误,Module B找不到aar文件。(同时如果又有Module C 依赖了Module B,C也会出同样的问题) ![](data:image/png;base64,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) 解法: 1、正常给一个module加入aar文件的步骤是: - 把aar文件放入module文件夹下libs包下 - 然后在项目的build.gradle文件的android节点下加入 - <table> <tr> <td> <div class="top-box hide"> </div> <div class="top-box hide"> </div> ``` repositories { flatDir { dirs ’libs' } } </td> </tr> </table> - 然后继续在dependencies节点中加入:compile(name: &#8216;xxxxxxx&#8217;, ext: &#8216;aar&#8217;) </div> <div> </div> <div> 2、就是这样会引发上面的问题,所以你要做的是,给所有依赖或间接依赖Module A 的Module的build.gradle的android节点下加入 </div> <div> repositories { </div> <div> <div class="top-box hide"> flatDir { dirs &#8216;../模块名称/libs&#8217;,&#8217;libs&#8217; } } </div> 其中dirs前面一段路径是Module A的文件夹 </div> <div> </div> <div> 问题原因: </div> <div> 对于Module B和Module C来说,他们依赖了Module A,不管用不用,他们都会去把Module A的依赖走一遍,当走到你添加的aar本地依赖时,他们去找aar的路径也需要你给出,而且给的方式如果是libs这样的路径,它会去找自己包下的libs,里边自然没有,所以你要给出另一个相对路径:../模块名称/libs这样才能找到,而为了不影响自己这个Module对自己Module下的libs的引用,就使用逗号再添加一个路径 </div>

2017年3月3日 · 1 分钟 · 天边的星星