java - 从 Android 中的外部 XML 文件访问元素
问题描述
我正在开发一个 Android 应用程序。我为布局创建了另一个 XML 文件:-
聊天文件.XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:background="@color/suitableblack"
android:orientation="vertical">
<Button
android:id="@+id/signout"
android:layout_width="422dp"
android:layout_height="64dp"
android:text="Button" />
<ListView
android:id="@+id/Msgdisplay"
android:layout_width="374dp"
android:layout_height="593dp"
android:layout_below="@id/signout"
android:layout_marginLeft="20dp"
android:forceDarkAllowed="false" />
<LinearLayout
android:layout_width="390dp"
android:layout_height="83dp"
android:layout_below="@id/Msgdisplay"
android:layout_marginLeft="20dp"
android:orientation="horizontal">
<EditText
android:id="@+id/Msginput"
android:layout_width="482dp"
android:layout_height="67dp"
android:layout_weight="1"
android:ems="10"
android:inputType="textPersonName"
android:text="Name" />
<Button
android:id="@+id/Sendbtn"
android:layout_width="match_parent"
android:layout_height="68dp"
android:layout_weight="1"
android:text="Button" />
</LinearLayout>
所以我想在我的 MainActivity.java 文件中使用 ID-Sendbtn 访问按钮,该部分的代码在这里:-
Button sendbtn=findViewById(R.id.Sendbtn);
sendbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String msg=message.getText().toString();
if(msg.length()==0)
{
Toast.makeText(getApplicationContext(),"Blank message detected",Toast.LENGTH_SHORT);
}
else
{
FirebaseDatabase.getInstance().getReference().push().setValue(new chatcolumns(msg,FirebaseAuth.getInstance().getCurrentUser().getDisplayName()));
}
}
});
但是每当我运行此代码时,它都会给我以下错误:-
Process: com.example.anochatzone, PID: 18398
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.anochatzone/com.example.anochatzone.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.example.anochatzone.MainActivity.onCreate(MainActivity.java:87)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
我的主要问题是如何从 MainActivity.java 中的 chatfile.xml 访问按钮
更新 MainActivity.java
package com.example.anochatzone;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.*;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.FirebaseDatabase;
import java.util.Objects;
public class MainActivity extends AppCompatActivity {
private FirebaseAuth authenticate;
private String email_str="";
private String password_str="";
private EditText email,password,message;
private Button loginbtn,resetbtn,sendbtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //will hide the title
Objects.requireNonNull(getSupportActionBar()).hide(); // hide the title bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //enable full screen
setContentView(R.layout.activity_main);
email=findViewById(R.id.EmailInput);
password=findViewById(R.id.Passwordinput);
message=findViewById(R.id.Msginput);
loginbtn=findViewById(R.id.Loginbtn);
resetbtn= findViewById(R.id.ResetBtn);
sendbtn=findViewById(R.id.Sendbtn);
authenticate=FirebaseAuth.getInstance();
loginbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"Please wait while we are processing your request........",Toast.LENGTH_SHORT).show();
email_str=email.getText().toString();
password_str=password.getText().toString();
if(email_str.length()==0||password_str.length()==0)
{
Toast.makeText(getBaseContext(),"Please check email and password",Toast.LENGTH_LONG).show();
}
else
{
authenticate.signInWithEmailAndPassword(email_str,password_str).addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
Log.d("User display name" , FirebaseAuth . getInstance() . getCurrentUser().getDisplayName());
Toast.makeText(getApplicationContext(),"Welcome "+email_str+" you have sucessfully logged in",Toast.LENGTH_LONG).show();
setContentView(R.layout.chatfile);
}
else
{
Toast.makeText(getApplicationContext(),"Failed to sign in .Please check internet connection or try again later",Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
sendbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String msg=message.getText().toString();
if(msg.length()==0)
{
Toast.makeText(getApplicationContext(),"Blank message detected",Toast.LENGTH_SHORT);
}
else
{
FirebaseDatabase.getInstance().getReference().push().setValue(new chatcolumns(msg,FirebaseAuth.getInstance().getCurrentUser().getDisplayName())) ;
}
}
});
}
}
解决方案
根据您的目的,当您启动或启动应用程序时,会出现登录页面。如果登录成功,就会出现聊天页面。
因此,您需要将您的活动分为两个活动,例如LoginActivity
启动器活动和ChatActivity
(MainActivity),如下所示。
对于登录页面,可能是一个activity_login.xml
和LoginActivity.java
在activity_login.xml
<!-- You need one button for login action. -->
<Button
android:id="@+id/btnLogin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Login"
/>
在LoginActivity.java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This line is important to access your resource id
setContentView(R.layout.activity_login);
findViewById(R.id.btnLogin).setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
// isLoginSuccess is an example condition for you
if (isLoginSuccess) {
// Navigate to mainpage
startActivity(new Intent(LoginActivity.this, MainActivity.class));
// Terminate the login activity for one time show.
finish();
} else {
// TODO: Try again implementations
}
}
});
}
对于主页,像上面一样,你需要一个activity_main.xml
和一个MainActivity.java
在Chatfile.xml
// other codes....
<Button
android:id="@+id/Sendbtn"
android:layout_width="match_parent"
android:layout_height="68dp"
android:layout_weight="1"
android:text="Button" />
// other codes....
在MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This line is important for your 'chatfile.xml'
setContentView(R.layout.Chatfile);
// You can access id `SendBtn` right now.
findViewById(R.id.SendBtn).setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
// TODO: implement something here.
}
});
}
在AndroidManifest.xml
中,您需要将启动器活动更改为LoginActivity
。
<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/AppTheme">
<activity android:name=".LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"/>
</application>
根据我的解决方案,您不必考虑登录成功或失败时应该隐藏什么 ui 元素。
如果我的回答有任何问题,请随时告诉我。
推荐阅读
- python - Azure - 如何从 Azure Databricks Filestore 下载文件?
- integromat - 自定义 Integromat 应用程序中没有“名称”属性的输入参数
- python - Numpy:在另一个二维数组中查找二维数组的对应关系,而不考虑顺序
- azure - 如何使用 azure Active Directory(无 p1、p2 订阅)创建具有权限的不同用户角色?
- php - CodeIgniter 4 - 如何在视图中显示 Flashdata?
- ios - 如何在 iOS 中使用 Pubnub Swift 将消息发布到频道
- javascript - 重构基于键/值对的值进行过滤的代码
- elasticsearch - 想要从 elasticsearch 获得点击部分的不同记录
- rust - 从 TcpListener 分派 Rust TcpStream 到循环中的分离方法
- c++ - 为什么一个简单的链表反向函数总是返回最后一个节点而不是第一个节点