在安卓开发过程中,难免会遇到一系列蛋疼的问题,解决姿势基本都是谷歌、百度,但是时间久了还是会忘记,所以有必要做一下总结,下次遇到可以方便快速的查看并解决。
Gradle配置
http://wuxiaolong.me/categories/Gradle/
AndroidStudio统一版本问题
在开发的过程中,难免会在项目中依赖一些第三方的或者自己封装的Librariy,此时不同的lib中builde.gradle中依赖的库版本可能不一样,所以我们要统一整个项目中所依赖的库版本
解决办法如下:
1、在整个项目中新建config.gradle:
ext{
android=[
compileSdkVersion : 26,
minSdkVersion : 21,
targetSdkVersion : 26,
versionCode : 1,
versionName : "1.0",
androidSupportVersion : "26.0.1",
retrofitVersion : "2.3.0",
rxJavaVersion : "2.1.0",
rxAndroidVersio : "2.0.1",
okhttpVersion : "3.6.0",
constraintlayou : "1.1.0-beta3",
gsonVersion : "2.8.0",
glideVersion : "3.7.0",
]
dependencies=[
"appcompat-v7" : "com.android.support:appcompat-v7:${android["androidSupportVersion"]}",
"constraint-layout" :"com.android.support.constraint:constraint-layout:${android["constraintlayout"]}",
"design" :"com.android.support:design:${android["androidSupportVersion"]}",
"retrofit" :"com.squareup.retrofit2:retrofit:${android["retrofitVersion"]}",
"retrofit-adapter-rxjava" :"com.squareup.retrofit2:adapter-rxjava2:${android["retrofitVersion"]}",
"retrofit-converter-gson" :"com.squareup.retrofit2:converter-gson:${android["retrofitVersion"]}",
"okhttp" :"com.squareup.okhttp3:okhttp:${android["okhttpVersion"]}",
"okhttp-logging-interceptor" :"com.squareup.okhttp3:logging-interceptor:${android["okhttpVersion"]}",
"rxjava" :"io.reactivex.rxjava2:rxjava:${android["rxJavaVersion"]}",
"rxandroid" :"io.reactivex.rxjava2:rxandroid:${android["rxAndroidVersion"]}",
"gson" :"com.google.code.gson:gson:${android["gsonVersion"]}",
"glide" :"com.github.bumptech.glide:glide:${android["glideVersion"]}",
]
}
2、在整个项目中新建builde.gradle中添加:
apply from : "config.gradle"
3、在app或者lib的builde.gradle中添加:
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode rootProject.ext.android["versionCode"]
versionName rootProject.ext.android["versionName"]
dependencies {
compile rootProject.ext.dependencies["appcompat-v7
compile rootProject.ext.dependencies["constraint-layout"]
compile rootProject.ext.dependencies["design"]
compile rootProject.ext.dependencies["rxjava"]
compile rootProject.ext.dependencies["rxandroid"]
compile rootProject.ext.dependencies["gson"]
compile rootProject.ext.dependencies["glide"]
}
项目模块资源目录划分
在moudle下的builde.gradle的android下新建:
sourceSets {
main {
res.srcDirs =
[
'src/main/res',
'src/main/res-xxx1',//首页
'src/main/res-xxx2',//我的
'src/main/res-xxx3'//购物车
]
}
}
然后在src/main下创建对应的目录
AndroidStudio连不上手机
命令行执行(XXXX是执行第一行之后显示的第一个端口号):
netstat -aon|findstr 5037
taskkill /pid XXXX /f沉浸式状态栏
https://github.com/laobie/StatusBarUtil
https://github.com/gyf-dev/ImmersionBar
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
禁止滑动布局如ScorllView、RecyclerView滑到顶部的波浪背影效果
android:scrollbars="none"
android:fadingEdge="none"
android:overScrollMode="never"
Activity的状态保存
在 Activity 生命周期中,Android 会在销毁 Activity 之前调用 onSaveInstanceState(),以便您保存有关应用状态的数据。 然后,您可以在 onCreate() 或 onRestoreInstanceState() 期间恢复 Activity 状态。
Activity之间的传值
1、传递List
ArrayList<String> info = new ArrayList<String>();
info.add(name);
info.add(website);
info.add(weibo);
Intent intent = new Intent(MainActivity.this, ResultActivity.class);
intent.putStringArrayListExtra("StringList", info);
startActivity(intent);
取出List
ArrayList<String> infoList = new ArrayList<String>();
infoList = getIntent().getStringArrayListExtra("StringList");
2、传递Object
1 使用Serializable方式
前提:Object需要实现Serializable接口
用Serializable方式传递Object的语法:bundle.putSerializable(key,object);
用Serializable方式接收Object的语法:object=(Object) getIntent().getSerializableExtra(key);
实现Serializable接口就是把对象序列化,然后再传输,和Java的常用编程没什么明显区别,而且Object不需要明显改变,推荐用这种方式。3、传递存储的Object的List
ArrayList<SerInfo> listObj = new ArrayList<SerInfo>();
SerInfo serInfo1 = new SerInfo(name, website, weibo);
SerInfo serInfo2 = new SerInfo(name, website, weibo);
listObj.add(serInfo1);
listObj.add(serInfo2);
Intent intent = new Intent();
intent.setClass(MainActivity.this, ResultActivity.class);
intent.putExtra("listobj", (Serializable) listObj);
startActivity(intent);
取出
ArrayList<SerInfo> listObj = (ArrayList<SerInfo>) getIntent().getSerializableExtra("listobj");
切换Fragment
private void initFragment() {
mOnLineGoodsFragment();
mOffLineGoodsFragment = new OffLineGoodsFragment();
//添加到数组
mFragments = new Fragment[]{mOnLineGoodsFragment, mOffLineGoodsFragment};
//开启事务
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
//添加首页
ft.add(R.id.frame_content, mFragments[0]).commit();
//默认设置为第0个
setIndexSelected(0);
}
private void setIndexSelected(int index) {
if (mIndex == index) {
return;
}
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
//隐藏
ft.hide(mFragments[mIndex]);
//判断是否添加
if (!mFragments[index].isAdded(){
ft.add(R.id.frame_content, mFragments[index]).show(mFragments[index]);
} else {
ft.show(mFragments[index]);
}
ft.commit();
//再次赋值
mIndex = index;
}
TextView
https://www.2cto.com/kf/201708/668884.html
让TextView部分文字显示其他颜色出了使用SpannableString 外还可以使用:
<string name="hth_signed_people">
<Data><![CDATA[<font color="#fd5729">%1$s/</font>%2$s人已报名]]></Data>
</string>
tv.setText(Html.fromHtml(String.format(getResources().getString(R.string.xxxxxxx),"222","33333" ));
EditText
自定义光标并且去除下划线
android:textCursorDrawable="@drawable/edit_cuser_color"
android:background="@null"
“edit_cuser_color”:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:width="2dp" />
<solid android:color="@color/green_71C74C" />
</shape>
禁止换行
android:maxLines="1"
android:singLine="true"
EditText设置可以编辑和不可编辑状态
EditText searchView = (EditText) findViewById(R.id.search_text);
searchView.setOnFocusChangeListener(new android.view.View.
OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
} else {
// 此处为失去焦点时的处理内容
}
}
});searchView.setFocusable(true);
searchView.setFocusableInTouchMode(true);
searchView.requestFocus();searchView.clearFocus();//失去焦点
searchView.requestFocus();//获取焦点ImageView
PopupWindow
http://blog.csdn.net/zhuwentao2150/article/details/52171794
AndroidStudio常用快捷键
1.全局搜索文件:双击Shift
2.Ctrl+Q:把光标移至方法处,按此组合键可快速查看方法的说明文档
3.Ctrl + + 展开代码
4.Ctrl + - 折叠代码
5.Ctrl+Alt+ left/right 返回至上次浏览的位置
http://blog.csdn.net/Me_Dong/article/details/53037201clipToPadding解决listview滚动问题
clipToPadding:
就是说控件的绘制区域是否在padding里面的,true的情况下如果你设置了padding那么绘制的区域就往里 缩,假设 内部有个属性设置了PaddingTop但是滑动的时候就忽视paddingTop的 则使用该属性如设置android:clipToPadding=falseclipChildren:
还有个类似的clipChildren,这个的作用是,如果子view比parent大的时候,是否裁剪,默认为true裁剪。也是在绘制阶段作用的。
举个例子,在100*100的布局里放个200*200的button会怎么样?
默认情况下,Button被裁剪,只有parent内部的可以显示,clipChildren设置为true之后,如右图所示,整个button都显示出来了,非常简单.注意android:clipChildren=”false”必须在最外层布局里写才有效果。这个属性在做动画的时候非常有用,因为默认是被裁剪的,所以一个view无法超过parent,在放大或者移动的动画中就可能被裁剪,用了此属性就不会被裁剪了。1、clipToPadding 是否可以在padding区域内绘制
2、子view是否可以超出父view的区域自定义View的问题
自定义属性的两种方法
RxTools
http://blog.csdn.net/m0_37314675/article/details/77850849
懒加载
public abstract class BaseLazyFragment extends Fragment {
protected Activity mActivity;
protected View mRootView;
/**
* 是否对用户可见
*/
protected boolean mIsVisible;
/**
* 是否加载完成
* 当执行完onViewCreated方法后即为true
*/
protected boolean mIsPrepare;
/**
* 是否加载完成
* 当执行完onViewCreated方法后即为true
*/
protected boolean mIsImmersion;
protected ImmersionBar mImmersionBar;
private Unbinder unbinder;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mActivity = (Activity) context;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(setLayoutId(), container, false);
return mRootView;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, mRootView);
if (isLazyLoad()) {
mIsPrepare = true;
mIsImmersion = true;
onLazyLoad();
} else {
initData();
if (isImmersionBarEnabled())
initImmersionBar();
}
initView();
setListener();
}
@Override
public void onDestroy() {
super.onDestroy();
unbinder.unbind();
if (mImmersionBar != null)
mImmersionBar.destroy();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getUserVisibleHint()) {
mIsVisible = true;
onVisible();
} else {
mIsVisible = false;
onInvisible();
}
}
/**
* 是否懒加载
*
* @return the boolean
*/
protected boolean isLazyLoad() {
return true;
}
/**
* 是否在Fragment使用沉浸式
*
* @return the boolean
*/
protected boolean isImmersionBarEnabled() {
return true;
}
/**
* 用户可见时执行的操作
*/
protected void onVisible() {
onLazyLoad();
}
private void onLazyLoad() {
if (mIsVisible && mIsPrepare) {
mIsPrepare = false;
initData();
}
if (mIsVisible && mIsImmersion && isImmersionBarEnabled()) {
initImmersionBar();
}
}
/**
* Sets layout id.
*
* @return the layout id
*/
protected abstract int setLayoutId();
/**
* 初始化数据
*/
protected void initData() {
}
/**
* 初始化沉浸式
*/
protected void initImmersionBar() {
mImmersionBar = ImmersionBar.with(this);
mImmersionBar.keyboardEnable(true).navigationBarWithKitkatEnable(false).init();
}
/**
* view与数据绑定
*/
protected void initView() {
}
/**
* 设置监听
*/
protected void setListener() {
}
/**
* 用户不可见执行
*/
protected void onInvisible() {
}
/**
* 找到activity的控件
*
* @param <T> the type parameter
* @param id the id
* @return the t
*/
@SuppressWarnings("unchecked")
protected <T extends View> T findActivityViewById(@IdRes int id) {
return (T) mActivity.findViewById(id);
}
}