1.0 内容涉及特别多,写的原因也是给自己捋思路。ListView使用好麻烦。
2.0 先看最终的运行结果:
image
image
3.0 第一界面是作为自己熟悉<ConstraintLayout>标签,练手做的,体会如下:
Guideline控件超级有用,它会提供一个可以设置百分比的虚线,其他控件可以基于这个控件来摆放,这样可以解决不同机型界面不兼容的问题。下面是我的手机(华为荣耀play)运行的画面:
image
3.1 这个界面总共加了6个控件:
ImageView :2张图片
EditText :2个文本输入框,虽然一个是密码输入框,但是因为学习资料没有介绍,就没用先。
Button :2个按钮控件,剩下的都是辅助线,<Guideline>组件相当于一个强制隐藏的view块控件:
image
这里加了9条辅助线,列的分别是25%,50%,75%,行的分别是30%,50%,70%
之前控件的大小控制百度到只能用权重,可是在这个新的ConstraintLayout标签中,权重没有意义……
因为Guideline控件是下面语句控制百分比(30%):
app:layout_constraintGuide_percent="0.3"
没有在其他控件尝试过这行语句在其他控件能不能用。
3.2 新建一个项目,名字叫什么无所谓,我的叫“Portable_Antitheft”
文件目录如下:
image
这里面我的上一篇博文也说了“ActivityCollector”类和“BaseActivity”类的作用,可以无视,也不贴代码了,作用一个是提供活动的一次性销毁方法,一个是随时监控返回栈栈顶的活动是什么,便于调试。
其中新建文件夹“.../res/drawable-xhdpi”,里面是这个程序开发所用的所有图片。
image
image
3.3 先看第一个布局文件的代码:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="0dp" android:layout_height="0dp" android:background="@drawable/background" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" /> <ImageView android:id="@+id/imageView2" android:layout_width="149dp" android:layout_height="140dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@drawable/logo" app:layout_constraintBottom_toTopOf="@+id/guideline2" app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintHorizontal_bias="0.503" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" /> <EditText android:id="@+id/username" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="邮箱/手机号" android:maxLines="1" app:layout_constraintBottom_toTopOf="@+id/guideline9" app:layout_constraintEnd_toStartOf="@+id/guideline7" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/guideline6" app:layout_constraintTop_toTopOf="@+id/guideline8" app:layout_constraintVertical_bias="0.161" /> <EditText android:id="@+id/passward" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="密码 " android:maxLines="1" app:layout_constraintBottom_toTopOf="@+id/guideline2" app:layout_constraintEnd_toStartOf="@+id/guideline7" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/guideline6" app:layout_constraintTop_toBottomOf="@+id/username" app:layout_constraintVertical_bias="0.09" /> <android.support.constraint.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.5" /> <android.support.constraint.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.5" /> <Button android:id="@+id/loginbutton" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:text="登 录" app:layout_constraintBottom_toTopOf="@+id/guideline9" app:layout_constraintEnd_toStartOf="@+id/guideline7" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/guideline6" app:layout_constraintTop_toTopOf="@+id/guideline2" app:layout_constraintVertical_bias="0.2" /> <Button android:id="@+id/registerbutton" android:layout_width="0dp" android:layout_height="wrap_content" android:text="注 册" app:layout_constraintEnd_toStartOf="@+id/guideline7" app:layout_constraintStart_toStartOf="@+id/guideline6" app:layout_constraintTop_toBottomOf="@+id/loginbutton" /> <android.support.constraint.Guideline android:id="@+id/guideline6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.25" /> <android.support.constraint.Guideline android:id="@+id/guideline7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.75" /> <android.support.constraint.Guideline android:id="@+id/guideline8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.3" /> <android.support.constraint.Guideline android:id="@+id/guideline9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.7" /></android.support.constraint.ConstraintLayout>
这里用了一张普通图片当成背景图,也是通过xml文件的特性,简单点说,代码的先后顺序决定图片的叠加顺序。
这里手动改的只有一个id和app:layout_constraintGuide_percent="0.什么",因为辅助线加的时候默认多少dp,其他实现全靠Design中鼠标的拖拽。下面图解里面的内容,便于理解:
image
4.0 MainActivity.java
package com.example.portable_anti_theft;import android.content.Intent;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.Window;import android.widget.Button;public class MainActivity extends BaseActivity { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);// requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);// 隐藏系统标题栏
ActionBar actionbar = getSupportActionBar(); if (actionbar != null){
actionbar.hide();
}// 以下代码也可行,实现同样的效果// if (getSupportActionBar() != null){// getSupportActionBar().hide();// }
Button loginbutton = (Button) findViewById(R.id.loginbutton);
loginbutton.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
});
}
}这里简单的实现了两个功能:去掉了系统标题栏,再简单对“登录”按钮做了一个跳转,跳到第二个活动界面。
5.0 重点来了,activity_main2.xml:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Main2Activity"> <include android:id="@+id/include" layout="@layout/title" /> <ListView android:id="@+id/list_view" android:layout_width="wrap_content" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="@+id/include" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline3" app:layout_constraintVertical_bias="1.0" /> <android.support.constraint.Guideline android:id="@+id/guideline3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.08" /></android.support.constraint.ConstraintLayout>
不要问我(o(╥﹏╥)o)代码什么意思,好些自己也没看懂,全靠拖拽。
image
这里的ListView控件最上面的边边,约束于8%的辅助线,这样就不会盖住线上面的东西——自制标题栏。大家看到源代码里面总共才插入三个标签,第二个是滚动列表,第三个是辅助线,第一个是重点,划线的那种。
<include android:id="@+id/include" layout="@layout/title" />
先不管这行代码,我们作为一个自创标题栏的尊严,首先不能每个界面都写一个自己的控件吧,当然希望只要想用自创标题栏的时候简单加载一下最好,也能更好的降低代码的耦合性。
在res/layout文件夹中新建title.xml布局文件,右击layout文件夹,newLayout Resource File,
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/title_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_marginStart="8dp" android:layout_marginTop="4dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:gravity="center" android:text="后退" android:textColor="#ffffff" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/title_edit" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" /> <TextView android:id="@+id/title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:gravity="center" android:text="随身监控" android:textColor="#6A8759" android:textSize="24sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/title_edit" app:layout_constraintHorizontal_bias="0.506" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" /> <Button android:id="@+id/title_edit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:layout_marginBottom="8dp" android:gravity="center" android:text="设置" android:textColor="#ffffff" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" /></android.support.constraint.ConstraintLayout>
3个控件:"后退"Button、"随身监控"TextView、"设置"Button。
拖拽加约束:
image
搞定,然后回到activity_main2.xml文件添加载入代码即可。
<include android:id="@+id/include" layout="@layout/title" />
没错,用include关键词就导入了,相当方便。
6.0 没有用数据库来读取,用数组模拟。Main2Activity.java
package com.example.portable_anti_theft;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;import java.util.List;public class Main2Activity extends AppCompatActivity { private List<Fruit> fruitList = new ArrayList<>(); private String[] data = { "广西壮族自治区", "内蒙古自治区", "宁夏回族自治区", "西藏藏族自治区", "新疆维吾尔自治区", "香港特别行政区", "澳门特别行政区", "北京市", "天津市", "上海市", "重庆市", "吉林省", "辽宁省", "黑龙江省", "河北省", "河南省", "安徽省", "甘肃省", "山东省", "湖南省", "湖北省", "江苏省", "浙江省", "江西省", "云南省", "广西省", "贵州省", "海南省", "台湾省",}; @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ActionBar actionbar = getSupportActionBar(); if (actionbar != null) {
actionbar.hide();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
Main2Activity.this,android.R.layout.simple_list_item_1,data
);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}运行:
image
image
7.0 这时候,优化代码,找足够行数的图片,放在drawable-xhdpi目录下,做出一开始图片带文字的效果。
7.1 新建布局文件fruit_item.xml,里面就1个图片控件,1个文字控件,两根辅助线:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/guideline4" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.016" /> <TextView android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="50sp" android:layout_marginStart="16dp" android:gravity="center_vertical" app:layout_constraintBottom_toBottomOf="@+id/fruit_image" app:layout_constraintStart_toStartOf="@+id/guideline4" app:layout_constraintTop_toTopOf="@+id/fruit_image" app:layout_constraintVertical_bias="0.0" /> <android.support.constraint.Guideline android:id="@+id/guideline4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.15" /> <android.support.constraint.Guideline android:id="@+id/guideline5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.4" /></android.support.constraint.ConstraintLayout>
辅助线都是垂直方向的15%、40%,能放进内容。
然后将图片约束于父节点到15%,将文本约束到图片、父节点、15%和40%
7.2 在src/main/java/com/example/portable_anti_theft目录下,新建Fruit.java,水果的构造函数:
package com.example.portable_anti_theft;public class Fruit { private String name; private int imageId; public Fruit(String name,int imageId){ this.imageId =imageId; this.name = name;
} public String getName(){ return name;
} public int getImageId(){ return imageId;
}
}因为原来的学习代码用的是水果作为内容,我这边改成省份而已。
代码里面可以看出,构造函数提供一个双参,名字和图片,并提供调用方法getName()和getImageId()。
7.3 同层目录下新建FruitAdapter.java
package com.example.portable_anti_theft;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;public class FruitAdapter extends ArrayAdapter<Fruit> { private int resourceId; @Override
public View getView(int position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position);//获取当前项的Fruit实例
View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName()); return view;
} public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) { super(context, textViewResourceId, objects);
resourceId = textViewResourceId;
}
}这是个自定义适配器,继承自ArrayAdapter,并将泛型指向Fruit类
可见,提供一个三参的构造函数,第一个是活动或者说上下文,第二个是ListView子项布局的id,第三份传一个list数组,具体水果名称/数据。下面还将id赋值给resourceId。
Adapter是什么 :适配器,因为 ListView 是一个 View ,不能添加子项,因此在呈现数据的时候就需要某种工具将数据呈现在 ListView 上,而 Adapter 就能充当此角色。常用的 Adapter:ArrayAdapter、BaseAdapter等。
重写方法getView(),通过getItem()方法得到实例Fruit。然后LayoutInflater为这个子项加载传入的布局。 这里的LayoutInflater的inflate()方法接收3个参数,第3个意思是只让在父布局中声明的layout属性生效,但不会为这个View添加父布局。因为一旦View有了父布局之后,就不会添加到ListView中。
不过没理解也没关系(因为我也没理解),这是标准写法,想用的时候,两个字,盘他!
7.4 修改Main2Activity.java代码:
package com.example.portable_anti_theft;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.LayoutInflater;import android.widget.ArrayAdapter;import android.widget.ListView;import java.util.ArrayList;import java.util.List;public class Main2Activity extends AppCompatActivity { private List<Fruit> fruitList = new ArrayList<>(); private String[] data = { "广西壮族自治区", "内蒙古自治区", "宁夏回族自治区", "西藏藏族自治区", "新疆维吾尔自治区", "香港特别行政区", "澳门特别行政区", "北京市", "天津市", "上海市", "重庆市", "吉林省", "辽宁省", "黑龙江省", "河北省", "河南省", "安徽省", "甘肃省", "山东省", "湖南省", "湖北省", "江苏省", "浙江省", "江西省", "云南省", "广西省", "贵州省", "海南省", "台湾省",}; @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ActionBar actionbar = getSupportActionBar(); if (actionbar != null) {
actionbar.hide();
}
initFruits();//初始化水果数据
FruitAdapter adapter = new FruitAdapter(Main2Activity.this, R.layout.fruit_item, fruitList);
ListView listview = (ListView) findViewById(R.id.list_view);
listview.setAdapter(adapter);
} private void initFruits() {
Fruit apple1 = new Fruit(data[0], R.drawable.png001);
fruitList.add(apple1);
Fruit apple2 = new Fruit(data[1], R.drawable.png002);
fruitList.add(apple2);
Fruit apple3 = new Fruit(data[2], R.drawable.png003);
fruitList.add(apple3);
Fruit apple4 = new Fruit(data[3], R.drawable.png004);
fruitList.add(apple4);
Fruit apple5 = new Fruit(data[4], R.drawable.png005);
fruitList.add(apple5);
Fruit apple6 = new Fruit(data[5], R.drawable.png006);
fruitList.add(apple6);
Fruit apple7 = new Fruit(data[6], R.drawable.png007);
fruitList.add(apple7);
Fruit apple8 = new Fruit(data[7], R.drawable.png008);
fruitList.add(apple8);
Fruit apple = new Fruit(data[8], R.drawable.png009);
fruitList.add(apple);
Fruit apple9 = new Fruit(data[9], R.drawable.png0010);
fruitList.add(apple9);
Fruit apple10 = new Fruit(data[10], R.drawable.png0011);
fruitList.add(apple10);
Fruit apple11 = new Fruit(data[11], R.drawable.png0012);
fruitList.add(apple11);
Fruit apple12 = new Fruit(data[12], R.drawable.png0013);
fruitList.add(apple12);
Fruit apple13 = new Fruit(data[13], R.drawable.png0014);
fruitList.add(apple13);
Fruit apple14 = new Fruit(data[14], R.drawable.png0015);
fruitList.add(apple14);
Fruit apple15 = new Fruit(data[15], R.drawable.png0016);
fruitList.add(apple15);
Fruit apple16 = new Fruit(data[16], R.drawable.png0017);
fruitList.add(apple16);
Fruit apple17 = new Fruit(data[17], R.drawable.png0018);
fruitList.add(apple17);
Fruit apple18 = new Fruit(data[18], R.drawable.png0019);
fruitList.add(apple18);
Fruit apple19 = new Fruit(data[19], R.drawable.png0020);
fruitList.add(apple19);
Fruit apple20 = new Fruit(data[20], R.drawable.png0021);
fruitList.add(apple20);
Fruit apple21 = new Fruit(data[21], R.drawable.png0022);
fruitList.add(apple21);
Fruit apple22 = new Fruit(data[22], R.drawable.png0023);
fruitList.add(apple22);
Fruit apple23 = new Fruit(data[23], R.drawable.png0024);
fruitList.add(apple23);
Fruit apple24 = new Fruit(data[24], R.drawable.png0025);
fruitList.add(apple24);
Fruit apple25 = new Fruit(data[25], R.drawable.png0026);
fruitList.add(apple25);
Fruit apple26 = new Fruit(data[26], R.drawable.png0027);
fruitList.add(apple26);
Fruit apple27 = new Fruit(data[27], R.drawable.png0028);
fruitList.add(apple27);
Fruit apple28 = new Fruit(data[28], R.drawable.png0029);
fruitList.add(apple28);
}
}这里新建了一个方法initFruits(),作用就是初始化数据化载入,将名字和图片id传入。
初始化数据,然后创建FruitAdapter实例,传入3个参数,1个是活动本身,1个是摆放布局,1个空数据。
创建下拉列表,加载下拉列表数据,接着将FruitAdapter实例的数据加载到下拉列表中。
运行在开始已。
7.5 这里有个问题,在初始化方法initFruits()中,可见时一个一个数据加载的特别四班,可是图片id传入吗,没找到用参数传的办法,没办法一个个操作的。
8.0 这里需要对ListView的运行效率进行优化,在代码中,FruitAdapter中的getView()方法中,每次布局都用重新加载一遍,当列表快速滚动时,将会出现性能的瓶颈。
在getView()方法中还有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便以后可以重用,修改FruitAdapter中getView()方法的代码:
public View getView(int position, View convertView, ViewGroup parent) {
Fruit fruit = getItem(position);
View view; if (convertView != null){
view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
}else{
view = convertView;
}
TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
fruitImage.setImageResource(fruit.getImageId());
fruitName.setText(fruit.getName()); return view;
}
作者:我睡醒刚刚
链接:https://www.jianshu.com/p/3dd37fd8d46e
共同學習,寫下你的評論
評論加載中...
作者其他優質文章











