一、基础

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() &#123;
    public String format(int value) &#123;
        String tmpStr = String.valueOf(value);
        if (value < 10) &#123;
            tmpStr = "0" + tmpStr;
        &#125;
        return tmpStr;
    &#125;
&#125;);

ListView

点击事件

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() &#123;
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) &#123;
        Toast.makeText(MainActivity.this, id+"", Toast.LENGTH_LONG).show();
    &#125;
&#125;);

点击失效

item添加android:descendantFocusability="blocksDescendants"

该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。

属性的值有三种:

beforeDescendants:viewgroup会优先其子类控件而获取到焦点

afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

长按点击

listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() &#123;
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) &#123;
                return true;
            &#125;
&#125;

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 &#123;
    private List<Poetry> poetryListData;
    private LayoutInflater layoutInflater;

    class ViewHolder &#123;
        TextView poetryTitleTV;
        TextView authorNameTV;
        Switch openSwitch;
    &#125;

    public QuestionAdapter(Context context) &#123;
        layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    &#125;

    public void setDataList(List<Poetry> list) &#123;
        poetryListData = list;
    &#125;

    @Override
    public int getCount() &#123;
        if(poetryListData == null) &#123;
            return 0;
        &#125;
        return poetryListData.size();
    &#125;

    @Override
    public Object getItem(int position) &#123;
        return poetryListData.get(position);
    &#125;

    @Override
    public long getItemId(int position) &#123;
        return poetryListData.get(position).getId();
    &#125;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) &#123;
        ViewHolder viewHolder;
        // 没有多余的view,新建
        if(convertView == null) &#123;
            // 将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,获取
        &#125; else &#123;
            viewHolder = (ViewHolder) convertView.getTag();
        &#125;
        viewHolder.poetryTitleTV.setText( poetryListData.get(position).getTitle() );
        viewHolder.authorNameTV.setText( poetryListData.get(position).getAuthorName() );
        viewHolder.openSwitch.setChecked(poetryListData.get(position).getStatus() == 1);
        return convertView;
    &#125;
&#125;

其他包

图像加载

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 &#123;
    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'

&#125;

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() &#123;
            @Override
            public void handleMessage(@NonNull Message msg) &#123;
                super.handleMessage(msg);
                List<Poetry> dataList = (List<Poetry>) msg.obj;
                poetryListData.clear();
                poetryListData.addAll(dataList);
                questionAdapter.notifyDataSetChanged();
            &#125;
        &#125;;

异步线程

// 异步获取一下数据
    private void getListData() &#123;
        new Thread(() -> &#123;
            List<Poetry> dataList = myDatabase.poetryDao().getAll();
            Message msg = new Message();
            msg.obj = dataList;
            handler.sendMessage(msg);
        &#125;).start();
    &#125;

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 &#123;
    @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) &#123;
        this.id = id;
        this.title = title;
        this.authorName = authorName;
        this.content = content;
        this.status = status;
    &#125;

    @Ignore
    public Poetry(String title, String authorName, String content, int status) &#123;
        this.title = title;
        this.authorName = authorName;
        this.content = content;
        this.status = status;
    &#125;
&#125;

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 &#123;

    @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);

&#125;

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 = &#123;Poetry.class&#125;, version = 1, exportSchema = false)
public abstract class MyDatabase extends RoomDatabase &#123;

    private static final String DATABASE_NAME = "ming_poetry_db";

    private static MyDatabase databaseInstance;

    public static synchronized MyDatabase getInstance(Context context)
    &#123;
        if(databaseInstance == null)
        &#123;
            databaseInstance = Room
                    .databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME)
//                    .allowMainThreadQueries()
                    .build();
        &#125;
        return databaseInstance;
    &#125;

    public abstract PoetryDao poetryDao();
&#125;