由于在学习手机软件开发,因此开一个分享Android Studio的坑。本篇博客将分享Android Studio中登录页面制作,跳转以及在一个layout中如何适配多个layout。本项目的代码我已分享在我的分享中,想要的可以自行下载。项目界面如下:
开始之前先来介绍一下本项目的项目结构,项目截图如下:
这里是项目Java代码的部分,先来看manifest文件夹,该文件夹中只有一个AndroidMainfest.xml文件,该文件作用主要是设置该项目的名字,项目图标以及项目中的Activities。很多朋友copy了一个activity就去运行,结果报错了,原因就是没有往AndroidMainfest.xml中添加新加入的active。本项目的xml如下,附带注释
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.homework2"
tools:ignore="MissingLeanbackLauncher">
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.software.leanback"
android:required="true" />
<!--
android:icon 启动图标
android:label App的名称
android:supportsRtl 支持右对齐,这个大家可以自行搜索
android:theme 本项目主题,主题就类似与样式
<activity
android:name activity的名称
android:exported 能否被其他应用程序组件调用或跟它交互,一般为true
<intent-filter>
用来注册 Activity 、 Service 和 Broadcast Receiver 具有能在某种数据上执行一个动作的能力
<action android:name 指定对响应的动作名
<category android:name="android.intent.category.LAUNCHER" 作为应用程序的启动项
</intent-filter>
/>
如果activity是复制过来项目的,至少要在这个文件加上一下信息:
<activity
android:name="这个activity的相对路径"
android:exported="true"/>
-->
<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.Homework2">
<activity
android:name=".activity.ListScenicSpot"
android:exported="false" />
<activity
android:name=".activity.MainActivity"
android:exported="true"/>
<activity android:name=".activity.LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
接下来就是java文件夹,里面存放要运行的java代码。其中activity里面放着页面运行的代码;adapter文件夹存放适配器代码;entity存放着item类本项目先不涉及联网获取item,目前是本地item;util里面存放常用的文件,这里面的AdvanceDecoration.java是用于定义item所在layout的样式
接下来就是res文件夹,里面存放要运行的资源文件,比如layout,字符,颜色,主题,图片等。其中anim文件夹存放动画xml文件;drawable存放图片资源;layout存放布局xml文件;mipmap存放启动图标资源;values存放一些值文件,比如字符值,color值,dimen尺寸值等。
接下来先从登录页面来详细介绍该项目。先来看LoginActivity
package com.example.homework2.activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
import com.example.homework2.R;
/*
* Main Activity class that loads {@link MainFragment}.
*/
public class LoginActivity extends FragmentActivity {
EditText userid, password;//定义两个editText,就是输入框
TextView log_info;
Button login_ok;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);//显示layout
userid = (EditText) this.findViewById(R.id.login_userid);//通过id来寻找editText
password = (EditText) this.findViewById(R.id.login_password);
log_info = (TextView) this.findViewById(R.id.login_errInfo);
login_ok = (Button) this.findViewById(R.id.login_ok);
// 另一种监听方式
// login_ok.setOnClickListener(view -> {
// String userId=userid.getText().toString().trim();
// String pwd=password.getText().toString();
// if (userId.equals("1") && pwd.equals("1")) {
// Intent intent1 = new Intent(LoginActivity.this, MainActivity.class);
// intent1.putExtra("userId",userId);
// startActivity(intent1);//启动另一activity
// } else {
// log_info.setText("登录失败!");
// }
// });
}
//事件过程,参数表示事件发生的控件对象,在登录这个按钮中有一个onClikc属性,用于设置点击事件触发的函数
public void clickLogin(View view) {
String userId=userid.getText().toString().trim();
String pwd=password.getText().toString();
// 如果用户名和密码都为1,则启动另一个页面
if (userId.equals("1") && pwd.equals("1")) {
// Intent 启动另一应用中的某个 Activity
Intent intent1 = new Intent(LoginActivity.this, MainActivity.class);
intent1.putExtra("userId",userId);//附带其他信息,以字典形式
startActivity(intent1);//启动另一activity
} else {
log_info.setText("登录失败!");
}
}
}
输入正确用户名和密码后将跳转到MainActivity,在MainActivity中将实现将item通过适配器放到每一个main_items这个layout中,再将每一个main_items放到recyclerView中,实现对item内容的展示。如果不理解的话,我用一张图来展示:
package com.example.homework2.activity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.homework2.R;
import com.example.homework2.adapter.RecyclerAdapter;
import com.example.homework2.entity.Item;
import com.example.homework2.util.AdvanceDecoration;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerview;
private List<Item> mData=new ArrayList<>();
private RecyclerAdapter mAdapter;
TextView userIdText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//通过id找到activity_main中展示item的RecycleView控件
mRecyclerview= (RecyclerView) findViewById(R.id.main_recycler);
//获取loginActivity中传过来的参数
String userId= getIntent().getStringExtra("userId");
userIdText =(TextView)this.findViewById(R.id.main_userid);
userIdText.setText(userId);
//垂直的Linearlayout线性布局
// LinearLayoutManager manager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
//网格布局的GridLayout
GridLayoutManager manager=new GridLayoutManager(this,2);
//获得数据,这里一般是从网络端中获取,本项目在本地中获取
initedata();
//输出数据大小,Log.e()方法用于在Logcat中输出信息
Log.e("data size=","" + mData.size());
mAdapter= new RecyclerAdapter(this,getLayoutInflater(),mData);
// mAdapter=new RecyclerAdapter(getApplicationContext(),getLayoutInflater(),mData);
//设置布局
mRecyclerview.setLayoutManager(manager);
mRecyclerview.setAdapter(mAdapter);
//添加分割线
mRecyclerview.addItemDecoration(new AdvanceDecoration(this, OrientationHelper.VERTICAL));
}
private void initedata() {
Item item =new Item("党史百年",R.drawable.ds);
Item item1=new Item("党章学习",R.drawable.dz);
Item item2=new Item("红色之旅",R.drawable.hszl);
Item item3=new Item("党史人物",R.drawable.dsrw);
Item item4=new Item("党史测试",R.drawable.dscs);
Item item5=new Item("通知公告",R.drawable.tzgg);
mData.add(item);
mData.add(item1);
mData.add(item2);
mData.add(item3);
mData.add(item4);
mData.add(item5);
}
}
//适配器代码如下
package com.example.homework2.adapter;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.homework2.R;
import com.example.homework2.activity.ListScenicSpot;
import com.example.homework2.entity.Item;
import java.util.List;
/**
* RecyclerAdapter继承了MyViewHolder
*/
public class RecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> {
private LayoutInflater mInflate;
private Context mContext;
private List<Item> mData;
public RecyclerAdapter(Context context, LayoutInflater mInflate, List<Item> mData) {
this.mContext=context;
this.mInflate = mInflate;
this.mData = mData;
}
@NonNull
/**
*
* @param viewGroup 父布局 RecyclerView
* @param i 相当于position
* @return ViewHolder
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
// 不需要检查是否复用,因为只要进入此方法,必然没有复用
// 因为RecyclerView 通过Holder检查复用
// 该方法为每一个Item创建一个Holder,在该项目中创建的Holder为MyViewHolder
View view = mInflate.inflate(R.layout.main_items,viewGroup,false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int position) {
// 该方法为每一个Item绑定ViewHolder,比如item中的title绑定tv,img绑定mImageview
myViewHolder.tv.setText(mData.get(position).getTitle());
myViewHolder.mImageview.setImageResource(mData.get(position).getImg());
}
@Override
public int getItemCount() {
// 该方法获得Item的数目,由于本项目的item不会发生变化,因此为mData为固定值
return mData.size();
}
//添加数据
public void addItem(Item data, int position) {
mData.add(position, data);
notifyItemInserted(position);
}
//删除数据
public void removeItem(Item data) {
int position = mData.indexOf(data);
mData.remove(position);
notifyItemRemoved(position);
}
}
/**
* MyViewHolder中获得子布局中的view
*/
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView tv;
ImageView mImageview;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
// 通常ViewHolder的构造,就是用于获取控件视图的
// 找到main_item中得控件
tv= (TextView) itemView.findViewById(R.id.main_item_title);
mImageview= (ImageView) itemView.findViewById(R.id.main_item_imageView);
// TODO 后续处理点击事件的操作
mImageview.setOnClickListener(this);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = getAdapterPosition();
Context context = tv.getContext();
String name = (String) tv.getText();
Toast.makeText(context,name,Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onClick(View view) {
int position = getAdapterPosition();
Context context = mImageview.getContext();
switch (position) {
case 2:
Intent intent = new Intent(context, ListScenicSpot.class);
context.startActivity(intent);
break;
default:
Toast.makeText(context,"该功能尚在开发中……",Toast.LENGTH_SHORT).show();
}
}
}
当点击红色之旅这个item的图片是,会跳转到一个新的页面,该页面也要用到item与适配器进行适配后显示到一个垂直的线性布局的RecyclerView中。相关代码其实与MainActivity类似。