android学习
布局相关
文件名的含义
drawable(图片)
layout(布局文件)
mipmap(启动图标)
values(常量) 里面的strings.xml比较重要可以放string常量
LinearLayout(horizontal)水平布局
LinearLayout(vertical)垂直布局
Gudeline 辅助线
打包apk
hint 提示
wrap_content 包裹内容(随着里面内容的大小进行改变)
水平紧凑
垂直紧凑
水平填满
垂直填满
水平连接
垂直连接
visbility
invisble 隐藏但是存在
gone 彻底隐藏
垂直辅助线
水平辅助线
垂直边界
水平边界
group 是全部分组
布局类型
FrameLayout(帧布局) 特点是可以互相覆盖
LinearLayout(线性布局) 可以互相嵌套
设置权重
android:layout_weight="1"
水平方向(默认)
android:orientation="horizontal"
垂直方向
android:orientation="vertical"
RelativeLayout(相对布局)
Activity 生命周期
//这是通过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);
}
});
也可以这么写
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方向旋转
? 创建横板副本
<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的对象
旧版本写法
新版写法
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
选项菜单写法
创建菜单文件夹和文件
写选项(要写在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">
添加新的页
在主包下添加窗口的注册
<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);
}
});
}
隐式跳转
<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);
必须先申请权限不然会报错
然后必须在模拟器中给权限才行
选择框写法
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();
}
自定义框写法
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
新建自定义样式
创建实体类
创建自定义Adapter
利用继承来的方法getItem 获取fruit 对象
使用自定义的Adapter 然后和listview组合
ListView的优化
可以重复利用view 利用convertView
如果缓存区是空的那么新建,否则用原来的view 可以节省内存
也可以吧属性打包提取出来就不用重新创建了
view.setTag()可以保存内容
viewgetTag()可以提取内容 但是出的是object类所以要强制转换回你要的类
ListView添加点击事件
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方法(膨胀器)
- 这玩意是用来将xml 转换为 view 的
- 这玩意不能直接new初始化,通过
Activity
和SystemService
获取,你也可以自定义他的工厂方法 - 因为性能问题,他只能把写在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
通过便利删除全部
杂项
大图片要放在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();
自定义控件
新建布局资源
使用自定义控件
layout="自定义控件路径"
<include layout="@layout/title"></include>
也可以通过类动态添加
通过膨胀器获取了当前的界面