android学习

android学习

布局相关

文件名的含义

drawable(图片)

layout(布局文件)

mipmap(启动图标)

values(常量) 里面的strings.xml比较重要可以放string常量

LinearLayout(horizontal)水平布局

LinearLayout(vertical)垂直布局

Gudeline 辅助线

image-20210111101908863

打包apk

hint 提示

wrap_content 包裹内容(随着里面内容的大小进行改变)

image-20210111111833563

水平紧凑

垂直紧凑

水平填满

垂直填满

水平连接

垂直连接

visbility

invisble 隐藏但是存在

gone 彻底隐藏

image-20210111112907687

垂直辅助线

水平辅助线

垂直边界

水平边界

group 是全部分组

布局类型

FrameLayout(帧布局) 特点是可以互相覆盖

LinearLayout(线性布局) 可以互相嵌套

设置权重

android:layout_weight="1"

水平方向(默认)

android:orientation="horizontal"

垂直方向

android:orientation="vertical"

RelativeLayout(相对布局)

image-20210114152754965

image-20210114153023729

Activity 生命周期

image-20210111141919542

//这是通过id找
textView = findViewById(R.id.textView);

代码绑定

button Click 事件写法

必须是View 类型的输入 并且没有返回值

本质上是监听器

buttonLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                display.setText(R.string.button1);
            }
        });

也可以这么写

image-20210113152449108

public void buttonClick(View view){

}

switch OnCheckedChange事件写法

 switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				if(isChecked == true){
                    display.setText("打开");
                }else {
                    display.setText("关闭");
                }
            }
        });

radioGroup事件写法

radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if(checkedId ==0){
                    //他找了drawable文件夹里面的图片
                    imageView.setImageResource(R.drawable.android);
                }else{
                    imageView.setImageResource(R.drawable.ios);
                }
            }
        });

Seekbar事件写法

seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    //值被改变
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        display.setText(String.valueOf(progress));
    }
	//一旦碰到拖动杆
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }
	//一旦停止触碰触发
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
});

cheakbox事件写法

Yuwen.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if(isChecked){
            Yuwenstr = "语文";
        }
        else {
            Yuwenstr = "";
        }
        display.setText(Yuwenstr+Suxuestr+Yingyustr);
    }
});

ratingbar事件写法

ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
    @Override
    public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
        Toast.makeText(getApplicationContext(),String.valueOf(rating),Toast.LENGTH_SHORT).show();
    }
});

弹出提示

Toast.makeText(getApplicationContext(),String.valueOf(rating),Toast.LENGTH_SHORT).show();

3个参数 1作用范围 2内容 3时间

最后要用.show()方法才能弹出

android本地化

android方向旋转

​ 创建横板副本

image-20210111194252469

<activity android:name=".MainActivity"
    android:screenOrientation="portrait">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

android:screenOrientation="portrait" 锁定为垂直

翻转时内容会被清空

public class MainActivity extends AppCompatActivity {
    Button button;
    TextView textView;
    @Override
    //savedInstanceState 是保存的内容
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        button = findViewById(R.id.button2);
        if(savedInstanceState !=null){
            //吧名叫KEY的string取出来了
            String s = savedInstanceState.getString("KEY");
            textView.setText(s);
        }
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.setText(R.string.button);

            }
        });
    }
	//保存临时内容
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        //吧内容 塞进KEY里了
        outState.putString("KEY", textView.getText().toString());
    }
}

android JetPack

ViewModel
public class MyViewModel extends ViewModel {
    public int number = 0;

}
//取法
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
textView = findViewById(R.id.textView);
textView.setText(String.valueOf(myViewModel.number));

我们只需要将想要被保存、被管理的变量,声明在继承了ViewModel的类中即可。然后通过ViewModelProviders.of()/get()拿到这个实例。就可能像往常一样自由的使用,而不需要担心Activity/Fragment重建所带来的一系列问题。

创建ViewModel的对象

旧版本写法

image-20210112092143420

新版写法

myViewModel = new ViewModelProvider(this).get(MyViewModel.class);

LiveDate

LiveData是配合ViewModel使用的

public class ViewModelWithLiveData extends ViewModel {
    private MutableLiveData<Integer> LikedNumber;

    public ViewModelWithLiveData() {
        LikedNumber = new MutableLiveData<>();
        LikedNumber.setValue(0);
    }

    public MutableLiveData<Integer> getLikedNumber() {
        return LikedNumber;
    }

    public void setLikedNumber(MutableLiveData<Integer> likedNumber) {
        LikedNumber = likedNumber;
    }
    public void addLikeNumber(int n){
        LikedNumber.setValue(LikedNumber.getValue()+n);
    }
}
private ViewModelWithLiveData viewModelWithLiveData;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = findViewById(R.id.textView);
    //这方法过期了
    viewModelWithLiveData = ViewModelProviders.of(this).get(ViewModelWithLiveData.class);
    viewModelWithLiveData.getLikedNumber().observe(this, new Observer<Integer>() {
        @Override
        public void onChanged(Integer integer) {
            textView.setText(String.valueOf(integer));
        }
    });
}
public void  buttonClick(View view){
    viewModelWithLiveData.addLikeNumber(1);
}
public void  button2Click(View view){
    viewModelWithLiveData.addLikeNumber(-1);
}

android前台写法

android:id="@+id/button"

添加id

选项菜单写法

创建菜单文件夹和文件

image-20210112104129064

写选项(要写在menu里)

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/add_item" android:title="add">

    </item>
    <item android:id="@+id/remove_item" android:title="remove">

    </item>
</menu>

添加进前台界面

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu,menu);
    return true;
}

使用选项

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {

    switch (item.getItemId()){
        case R.id.add_item:
            Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
            break;
        case R.id.remove_item:
            Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();
            break;
    }
    return super.onOptionsItemSelected(item);
}

去标题栏

<style name="Theme.ActivityTest" parent="Theme.MaterialComponents.DayNight.NoActionBar">

添加新的页

image-20210113095025679

在主包下添加窗口的注册

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.ActivityTest">
    <activity android:name=".SecondActivity"></activity>
    <activity android:name=".MainActivity">
        //过滤器
        <intent-filter>
            //这个是过滤器 表示现在是主程序
            <action android:name="android.intent.action.MAIN" />
			//这个是过滤器 表示是优先运行
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

页面的跳转

页面的跳转显式使用

public void initView(){
    button = findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //
            //跳转页面第一个参数是当前在哪里,第二个是跳去哪里
            Intent intent = new Intent(MainActivity.this,SecondActivity.class);
            //启动意图
            startActivity(intent);
        }
    });
}

隐式跳转

image-20210113102242894

<activity android:name=".SecondActivity">
    <intent-filter>
        //起了个名字
        <action android:name="START_ACTION"></action>
        <category android:name="android.intent.category.DEFAULT"></category>
    </intent-filter>
</activity>

隐式写法(添加了名字也不会影响显式的写法)

//跳转页面第一个参数是注册的窗口名 见图上
Intent intent = new Intent("START_ACTION");
//启动意图
startActivity(intent);

调用系统应用

通过隐式调用系统应用

//通过隐式调用系统应用
Intent intent = new Intent();
//打电话
intent.setAction(Intent.ACTION_CALL);
//电话号
intent.setData(Uri.parse("tel:13942322358"));
startActivity(intent);

必须先申请权限不然会报错

image-20210113103918517

然后必须在模拟器中给权限才行

选择框写法

new AlertDialog.Builder(this)
    
    	//标题
        .setTitle("删除记录确认")
    	//信息
        .setMessage("是否确认删除此纪录")
        //是否能取消
        .setCancelable(false)
    	//设置图片
    	.setIcon(R.drawable.ic_launcher_foreground)
    	//如果选择成功做什么处理
        .setPositiveButton("yes", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this,"成功",Toast.LENGTH_SHORT).show();
            }
        })
      //如果选择失败做什么处理
        .setNegativeButton("no", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this,"失败",Toast.LENGTH_SHORT).show();
            }
        })
        .show();

单选框写法

public void buttonClickCheckbox(View view){
    String[] colors = {"绿","红"};
    new AlertDialog.Builder(this)
            .setTitle("选择颜色")
            //第一个是选择的数组 第二个是默认第几个 , -1代表没有默认 , 第三个是选择以后的方法
            .setSingleChoiceItems(colors, 0, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(MainActivity.this,colors[which],Toast.LENGTH_SHORT);
                }
            })
        	//第二个方法参数可以为null
            .setPositiveButton("ok",null)
            .show();
}

自定义框写法

image-20210113162743575

Adapater(数组适配器的写法)

Adapter(适配器的讲解)

Adapter是用来帮助填出数据的中间桥梁,将各种数据以合适的形式显示在View中给用户看。Adapter有很多的接口、抽象类、子类可以使用。

public class GridAdapater extends BaseAdapter {
    private int resource;
    private Context context;
    private String[] names;
    private int[] icons;

    public GridAdapater(Context context,int resource,String[] names,int[] icons){
        this.resource =resource;
        this.context = context;
        this.names = names;
        this.icons = icons;

    }
    //列表长度(网格长度)
    @Override
    public int getCount() {
        return names.length;
    }

 	@Override
    public Object getItem(int position) {
        return names[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if(convertView==null){
            convertView = LayoutInflater.from(context).inflate(resource,parent,false);
            holder = new ViewHolder();
            //到这步开始绑定
            holder.imageid=convertView.findViewById(R.id.iv_grid_image);
            holder.textView = convertView.findViewById(R.id.iv_grid_text);
            convertView.setTag(holder);
        }
        else{
            holder= (ViewHolder)convertView.getTag();
        }
        //装配
        holder.imageid.setImageResource(icons[position]);
        holder.textView.setText(names[position]);
        return convertView;
    }
    class ViewHolder{
        ImageView imageid;
        TextView textView;
    }

ListView 控件的写法

listView = findViewById(R.id.lv_simple_listview);
//ArrayAdapter 数组适配器
//参数 第一个上下文 第二个是列表项布局资源(列表长什么样) 第三个是泛形数组提供列表数据(保存有列表项内容的数组)
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,data);
//适配器和 listview 组合起来
listView.setAdapter(adapter);

自定义ListView

新建自定义样式

image-20210115104225278

创建实体类

image-20210115104335392

创建自定义Adapter

利用继承来的方法getItem 获取fruit 对象

image-20210115104503019

使用自定义的Adapter 然后和listview组合

image-20210115105239775

ListView的优化

可以重复利用view 利用convertView

如果缓存区是空的那么新建,否则用原来的view 可以节省内存

image-20210115154843543

也可以吧属性打包提取出来就不用重新创建了

view.setTag()可以保存内容

viewgetTag()可以提取内容 但是出的是object类所以要强制转换回你要的类

image-20210115155325214

ListView添加点击事件

image-20210115160942951

view 就是当前选中的view

position 是当前的编号

id 是id

GridView的写法

numColumns 是 表格的列数

verticalSpacing 是行之间的间距

<GridView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:verticalSpacing="10dp"
    android:numColumns="3"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" >
    
</GridView>

inflate方法(膨胀器)

image-20210116114515916

  1. 这玩意是用来将xml 转换为 view
  2. 这玩意不能直接new初始化,通过ActivitySystemService获取,你也可以自定义他的工厂方法
  3. 因为性能问题,他只能把写在layout里被预处理过的 xml 转换为 view ,不能随便找个xml文件就让他转换

LayoutInflater是一个不能直接new的类,他来管 xml 转换为view

ViewHolder 的理解

要想使用 ListView 就需要编写一个 Adapter 将数据适配到 ListView上,而为了节省资源提高运行效率,一般自定义类 ViewHolder 来减少 findViewById() 的使用以及避免过多地 inflate view,从而实现目标。

android活动的启动模式

默认是standard

不管哪里都会创建新的

 android:launchMode="standard"

singleTop

如果在栈顶不会再创建了

如果从别的页跳回来还是会新建

android:launchMode="singleTop"

singleTask

不会新建

android:launchMode="singleTask"

singleInstance

独立返回栈

singleInstance

一键退出所有窗口

通过 list 保存所有Activity

通过便利删除全部

image-20210113134239622

image-20210113134258306

image-20210113134317852

杂项

大图片要放在drawble-hdpi 里

如果模拟器打不开可以试试删了再建一个

控件居中

android:layout_gravity="center"

垂直居中

android:layout_gravity="center_vertical"

水平居中(控件里)

android:gravity="center_horizontal"

match_parent表示让当前控件的大小和父布局的大小一样,也就是由父布局来决定当前控件的大小

android:layout_width="match_parent"

wrap_content表示让当前的控件大小能够刚好包含里面的内容,也就是由控件内容决定当前控件的大小

android:layout_height="wrap_content"

常用类

handler类在主线程和子线程传递信息

ActionBarDrawerToggle 创造左上角的按钮

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.app_name,R.string.app_name);
toggle.syncState();

image-20210114175656171

自定义控件

新建布局资源

image-20210114163554613

使用自定义控件

layout="自定义控件路径"

<include layout="@layout/title"></include>

也可以通过类动态添加

image-20210114170247330

通过膨胀器获取了当前的界面

image-20210114170350574

posted @ 2021-01-20 16:02  bad_op  阅读(192)  评论(2)    收藏  举报