一、基础
gradle
https://services.gradle.org/distributions/
C:\Users\yourname\.gradle\wrapper\dists\gradle-版本\随机字符串\
将gradle-版本.zip.part移除,把自己下载的gradle-gradle-版本.zip复制到这个目录。然后再次启动Andriod Studio,会自动读取gradle并解压
布局
xmlns:android="http://schemas.android.com/apk/res/android"
一、LinearLayout
线性布局
二、RelativeLayout
相对布局
三、FrameLayout
帧布局
foreground="@mipmap/ic_launcher" 始终前面
foregroundGrabity="left" 显示的位置
四、TableLayout
表格布局
五、AbsoluteLayout
绝对布局
控件属性
一、对齐
android:gravity:
这个是针对控件里的元素来说的,用来控制元素在该控件里的显示位置。例如,在一个Button按钮控件中设置如下两个属性,
android:gravity=”left”和android:text=”提交”,这时Button上的文字“提交”将会位于Button的左部。
android:layout_gravity:
这个是针对控件本身而言,用来控制该控件在包含该控件的父控件中的位置。同样,当我们在Button按钮控件中设置android:layout_gravity=”left”属性时,表示该Button按钮将位于界面的左部。
Mat
一、导航栏
@style/Theme.AppCompat.Light.NoActionBar
二、使用
// module app
{
api 'com.google.android.material:material:1.1.0-alpha06'
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
manifest
android:theme="@style/Theme.Shrine"
style
<!-- Base application theme. -->
<style name="Theme.Shrine" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="Widget.Shrine.Toolbar" parent="Widget.AppCompat.Toolbar">
<item name="android:background">?attr/colorAccent</item>
<item name="android:theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
<item name="popupTheme">@style/ThemeOverlay.AppCompat.Light</item>
</style>
组件
numberPick
afterTenTimeNP.setMaxValue(9);
afterTenTimeNP.setMinValue(0);
afterTenTimeNP.setValue(1);
// 格式化
afterTenTimeNP.setFormatter(new NumberPicker.Formatter() {
public String format(int value) {
String tmpStr = String.valueOf(value);
if (value < 10) {
tmpStr = "0" + tmpStr;
}
return tmpStr;
}
});
ListView
点击事件
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, id+"", Toast.LENGTH_LONG).show();
}
});
点击失效
item添加android:descendantFocusability="blocksDescendants"
该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。
属性的值有三种:
beforeDescendants
:viewgroup会优先其子类控件而获取到焦点
afterDescendants
:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants
:viewgroup会覆盖子类控件而直接获得焦点
长按点击
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
return true;
}
}
Dialog
铺满与定位
Dialog dialog = new DeleteClockDialog(MainActivity.this);
Window window = dialog.getWindow();
window.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
window.setBackgroundDrawableResource(android.R.color.white);
window.getDecorView().setPadding(0, 0, 0, 0);
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.FILL_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
dialog.show();
adapter
package com.ming.poetry.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Switch;
import android.widget.TextView;
import com.ming.poetry.R;
import com.ming.poetry.bean.Poetry;
import com.ming.poetry.ui.questionBank.QuestionBank;
import java.util.List;
public class QuestionAdapter extends BaseAdapter {
private List<Poetry> poetryListData;
private LayoutInflater layoutInflater;
class ViewHolder {
TextView poetryTitleTV;
TextView authorNameTV;
Switch openSwitch;
}
public QuestionAdapter(Context context) {
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setDataList(List<Poetry> list) {
poetryListData = list;
}
@Override
public int getCount() {
if(poetryListData == null) {
return 0;
}
return poetryListData.size();
}
@Override
public Object getItem(int position) {
return poetryListData.get(position);
}
@Override
public long getItemId(int position) {
return poetryListData.get(position).getId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
// 没有多余的view,新建
if(convertView == null) {
// 将itemView构建起来
convertView = layoutInflater
.inflate(R.layout.navigation_question_bank_list_item, parent, false);
// viewHolder,将每个view视图化
viewHolder = new ViewHolder();
viewHolder.poetryTitleTV = (TextView) convertView.findViewById(R.id.poetry_item_title_tv);
viewHolder.authorNameTV = (TextView) convertView.findViewById(R.id.poetry_item_author_name_tv);
viewHolder.openSwitch = (Switch) convertView.findViewById(R.id.poetry_item_close_switch);
// 将viewHolder填充进去
convertView.setTag(viewHolder);
// 有多余的view,获取
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.poetryTitleTV.setText( poetryListData.get(position).getTitle() );
viewHolder.authorNameTV.setText( poetryListData.get(position).getAuthorName() );
viewHolder.openSwitch.setChecked(poetryListData.get(position).getStatus() == 1);
return convertView;
}
}
其他包
图像加载
ImageView imageView = root.findViewById(R.id.test_image);
ImageLoaderConfiguration config = ImageLoaderConfiguration.createDefault(this.getActivity());
imageLoader.init(config);
imageLoader.displayImage("http://blog.mingyuefusu.cn/avatar.jpg", imageView);
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
二、工具
gradle
api 'com.google.android.material:material:1.1.0-alpha06'
implementation 'com.google.code.gson:gson:2.6.2'
annotationProcessor 'org.projectlombok:lombok:1.18.2'
compileOnly 'org.projectlombok:lombok:1.18.2'
code-Generate-GsonFormat
一般需要的依赖
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment:2.3.1'
implementation 'androidx.navigation:navigation-ui:2.3.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
annotationProcessor 'org.projectlombok:lombok:1.18.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
def room_version = "2.2.0-alpha01"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
compileOnly 'org.projectlombok:lombok:1.18.2'
}
room
依赖
def room_version = "2.2.0-alpha01"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
handle
handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
List<Poetry> dataList = (List<Poetry>) msg.obj;
poetryListData.clear();
poetryListData.addAll(dataList);
questionAdapter.notifyDataSetChanged();
}
};
异步线程
// 异步获取一下数据
private void getListData() {
new Thread(() -> {
List<Poetry> dataList = myDatabase.poetryDao().getAll();
Message msg = new Message();
msg.obj = dataList;
handler.sendMessage(msg);
}).start();
}
bean
package com.ming.poetry.bean;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
//@AllArgsConstructor
//@NoArgsConstructor
@Entity(tableName = "poetry")
public class Poetry {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
private int id;
@ColumnInfo(name = "title", typeAffinity = ColumnInfo.TEXT)
private String title;
@ColumnInfo(name = "author_name", typeAffinity = ColumnInfo.TEXT)
private String authorName;
@ColumnInfo(name = "content", typeAffinity = ColumnInfo.TEXT)
private String content;
@ColumnInfo(name = "status", typeAffinity = ColumnInfo.INTEGER)
private int status;
public Poetry(int id, String title, String authorName, String content, int status) {
this.id = id;
this.title = title;
this.authorName = authorName;
this.content = content;
this.status = status;
}
@Ignore
public Poetry(String title, String authorName, String content, int status) {
this.title = title;
this.authorName = authorName;
this.content = content;
this.status = status;
}
}
dao
package com.ming.poetry.dao;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import com.ming.poetry.bean.Poetry;
import java.util.List;
@Dao
public interface PoetryDao {
@Query("select * from poetry order by id desc")
List<Poetry> getAll() ;
@Insert
void insert(Poetry poetry);
@Update
void update(Poetry poetry) ;
@Delete
void delete(Poetry poetry);
@Query("SELECT * FROM poetry WHERE id = :id")
Poetry getPoetryById(int id);
}
database
package com.ming.poetry.database;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.DatabaseConfiguration;
import androidx.room.InvalidationTracker;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteOpenHelper;
import com.ming.poetry.bean.Poetry;
import com.ming.poetry.dao.PoetryDao;
@Database(entities = {Poetry.class}, version = 1, exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {
private static final String DATABASE_NAME = "ming_poetry_db";
private static MyDatabase databaseInstance;
public static synchronized MyDatabase getInstance(Context context)
{
if(databaseInstance == null)
{
databaseInstance = Room
.databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME)
// .allowMainThreadQueries()
.build();
}
return databaseInstance;
}
public abstract PoetryDao poetryDao();
}