diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1aeaa6b..fa6f916 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -50,6 +50,7 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + implementation("de.hdodenhof:circleimageview:3.1.0") // Retrofit implementation("com.squareup.retrofit2:retrofit:2.9.0") // Gson 转换器 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9ac6a21..78bae90 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,10 @@ + + + + + + diff --git a/app/src/main/java/com/example/defenseapplication/adapter/AddDeviceAdapter.kt b/app/src/main/java/com/example/defenseapplication/adapter/AddDeviceAdapter.kt new file mode 100644 index 0000000..e6f181a --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/adapter/AddDeviceAdapter.kt @@ -0,0 +1,40 @@ +package com.example.defenseapplication.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.defenseapplication.R + +data class Device( + val name: String, + val icon: String +) +class AddDeviceAdapter(private val devices: List, private val onItemClick: (Device) -> Unit) : + RecyclerView.Adapter() { + + inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val ivIcon: ImageView = itemView.findViewById(R.id.ivDeviceIcon2) + val tvName: TextView = itemView.findViewById(R.id.tvDeviceName2) // 注意:ID 要和布局中一致 + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context).inflate(R.layout.item_device2, parent, false) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val device = devices[position] + holder.tvName.text = device.name + // 根据 icon 字符串加载对应图片(假设 icon 是本地 drawable 的名称) + val resId = holder.itemView.context.resources.getIdentifier(device.icon, "drawable", holder.itemView.context.packageName) + if (resId != 0) holder.ivIcon.setImageResource(resId) else holder.ivIcon.setImageResource(R.drawable.img) + + // 设置点击事件 + holder.itemView.setOnClickListener { onItemClick(device) } + } + + override fun getItemCount(): Int = devices.size +} \ No newline at end of file diff --git a/app/src/main/java/com/example/defenseapplication/adapter/DeviceAdapter.kt b/app/src/main/java/com/example/defenseapplication/adapter/DeviceAdapter.kt index 4dedce7..4b54ecc 100644 --- a/app/src/main/java/com/example/defenseapplication/adapter/DeviceAdapter.kt +++ b/app/src/main/java/com/example/defenseapplication/adapter/DeviceAdapter.kt @@ -40,11 +40,11 @@ class DeviceAdapter( fun bind(item: DeviceUi) { binding.tvDeviceName.text = item.name if (item.isOnline) { - binding.tvDeviceStatus.text = "\u25CF 正在运行" - binding.tvDeviceStatus.setTextColor(binding.root.context.getColor(R.color.green)) + binding.tvDeviceName.text = "\u25CF 正在运行" + binding.tvDeviceName.setTextColor(binding.root.context.getColor(R.color.green)) } else { - binding.tvDeviceStatus.text = "\u25CF 离线" - binding.tvDeviceStatus.setTextColor(binding.root.context.getColor(R.color.red)) + binding.tvDeviceName.text = "\u25CF 离线" + binding.tvDeviceName.setTextColor(binding.root.context.getColor(R.color.red)) } binding.root.setOnClickListener { onItemClick(item) diff --git a/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt b/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt index 7d07526..90bc425 100644 --- a/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt +++ b/app/src/main/java/com/example/defenseapplication/home/AddDeviceActivity.kt @@ -1,21 +1,52 @@ package com.example.defenseapplication.home +import android.content.Intent import android.os.Bundle -import androidx.activity.enableEdgeToEdge +import android.view.View +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.example.defenseapplication.R +import androidx.recyclerview.widget.GridLayoutManager +import com.example.defenseapplication.adapter.AddDeviceAdapter +import com.example.defenseapplication.adapter.Device +import com.example.defenseapplication.databinding.AddDeviceActivityBinding class AddDeviceActivity : AppCompatActivity() { + + private lateinit var binding: AddDeviceActivityBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContentView(R.layout.add_device_activity) - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets + binding = AddDeviceActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.ivBack.setOnClickListener { + finish() + } + + setupDeviceList() + } + + private fun setupDeviceList() { + val devices = listOf( + Device("智能挂式防御机", "device1"), + Device("智能防御机", "device2") + ) + + if (devices.isEmpty()) { + binding.emptyState.visibility = View.VISIBLE + binding.rvDevices.visibility = View.GONE + } else { + binding.emptyState.visibility = View.GONE + binding.rvDevices.visibility = View.VISIBLE + + binding.rvDevices.layoutManager = GridLayoutManager(this, 2) + // 传入点击回调 + binding.rvDevices.adapter = AddDeviceAdapter(devices) { device -> + // 跳转到 AddFamilyActivity(选择Wi-Fi页面) + val intent = Intent(this, AddFamilyActivity::class.java) + intent.putExtra("device_name", device.name) + startActivity(intent) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/defenseapplication/home/AddFamilyActivity.kt b/app/src/main/java/com/example/defenseapplication/home/AddFamilyActivity.kt new file mode 100644 index 0000000..97343e6 --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/home/AddFamilyActivity.kt @@ -0,0 +1,158 @@ +package com.example.defenseapplication.home + +import android.Manifest +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.content.pm.PackageManager +import android.net.wifi.ScanResult +import android.net.wifi.WifiManager +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.Gravity +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.PopupWindow +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.defenseapplication.R +import com.example.defenseapplication.adapter.WifiListAdapter +import com.example.defenseapplication.databinding.AddFamilyActivityBinding +import com.example.defenseapplication.databinding.DialogWifiListBinding + +class AddFamilyActivity : AppCompatActivity() { + + private lateinit var binding: AddFamilyActivityBinding + private lateinit var wifiManager: WifiManager + private lateinit var wifiScanReceiver: BroadcastReceiver + private var popupWindow: PopupWindow? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = AddFamilyActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.ivBack.setOnClickListener { + finish() + } + + binding.btnSelectWifi.setOnClickListener { + showWifiListDialog() + } + + binding.etWifiName.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + + override fun afterTextChanged(s: Editable?) { + updateBottomButtonVisibility() + } + }) + + binding.btnConfirm.setOnClickListener { + // 确认添加设备逻辑 + } + + wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + + wifiScanReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false) + if (success) { + updateWifiList() + } + } + } + + val deviceName = intent.getStringExtra("device_name") + + binding.btnConfirm.setOnClickListener { + val intent=Intent(this, SetNameActivity::class.java) + startActivity( intent) + } + } + + private fun showWifiListDialog() { + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED || + ActivityCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, + arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE), + 1001) + return + } + + if (!wifiManager.isWifiEnabled) { + wifiManager.isWifiEnabled = true + } + + wifiManager.startScan() + + val dialogBinding = DialogWifiListBinding.inflate(LayoutInflater.from(this)) + popupWindow = PopupWindow( + dialogBinding.root, + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + isFocusable = true + setBackgroundDrawable(null) + setOnDismissListener { + binding.maskView.visibility = android.view.View.GONE + } + showAtLocation(window.decorView, Gravity.BOTTOM, 0, 0) + } + + binding.maskView.visibility = android.view.View.VISIBLE + + dialogBinding.rvWifiList.layoutManager = LinearLayoutManager(this@AddFamilyActivity) + + val wifiList = getWifiList() + dialogBinding.rvWifiList.adapter = WifiListAdapter(wifiList) { wifiName -> + binding.etWifiName.setText(wifiName) + popupWindow?.dismiss() + } + } + + private fun updateBottomButtonVisibility() { + val wifiName = binding.etWifiName.text.toString().trim() + binding.bottomButtonLayout.visibility = + if (wifiName.isNotEmpty()) android.view.View.VISIBLE else android.view.View.GONE + } + + private fun getWifiList(): List { + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED) { + return emptyList() + } + val results: List = wifiManager.scanResults + return results.map { it.SSID }.distinct() + } + + private fun updateWifiList() { + popupWindow?.contentView?.findViewById(R.id.rvWifiList)?.let { recyclerView -> + val wifiList = getWifiList() + recyclerView.adapter = WifiListAdapter(wifiList) { wifiName -> + binding.etWifiName.setText(wifiName) + popupWindow?.dismiss() + } + } + } + + override fun onStart() { + super.onStart() + val intentFilter = IntentFilter() + intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) + registerReceiver(wifiScanReceiver, intentFilter) + } + + override fun onStop() { + super.onStop() + unregisterReceiver(wifiScanReceiver) + popupWindow?.dismiss() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt b/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt index 856ea9c..c3a001c 100644 --- a/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt +++ b/app/src/main/java/com/example/defenseapplication/home/HomeMenuFragment.kt @@ -70,6 +70,14 @@ class HomeMenuFragment : Fragment() { val intent = Intent(requireContext(), MessageActivity::class.java) startActivity(intent) } + binding.add.setOnClickListener { + val intent = Intent(requireContext(), AddDeviceActivity::class.java) + startActivity(intent) + } + binding.addFamily.setOnClickListener { + val intent = Intent(requireContext(), AddFamilyActivity::class.java) + startActivity(intent) + } } private fun initView() { diff --git a/app/src/main/java/com/example/defenseapplication/home/SetNameActivity.kt b/app/src/main/java/com/example/defenseapplication/home/SetNameActivity.kt new file mode 100644 index 0000000..3070a7f --- /dev/null +++ b/app/src/main/java/com/example/defenseapplication/home/SetNameActivity.kt @@ -0,0 +1,25 @@ +package com.example.defenseapplication.home + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.example.defenseapplication.databinding.SetNameActivityBinding + +class SetNameActivity : AppCompatActivity() { + + private lateinit var binding: SetNameActivityBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = SetNameActivityBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.ivBack.setOnClickListener { + finish() + } + + binding.btnConfirm.setOnClickListener { + val deviceName = binding.etName.text.toString().trim() + finish() + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/back.png b/app/src/main/res/drawable/back.png new file mode 100644 index 0000000..65c0eaa Binary files /dev/null and b/app/src/main/res/drawable/back.png differ diff --git a/app/src/main/res/drawable/go_up.png b/app/src/main/res/drawable/go_up.png new file mode 100644 index 0000000..2c54b4c Binary files /dev/null and b/app/src/main/res/drawable/go_up.png differ diff --git a/app/src/main/res/drawable/ic_lock.png b/app/src/main/res/drawable/ic_lock.png new file mode 100644 index 0000000..e6d5f52 Binary files /dev/null and b/app/src/main/res/drawable/ic_lock.png differ diff --git a/app/src/main/res/drawable/ic_wifi.png b/app/src/main/res/drawable/ic_wifi.png new file mode 100644 index 0000000..1186ba0 Binary files /dev/null and b/app/src/main/res/drawable/ic_wifi.png differ diff --git a/app/src/main/res/layout/add_device_activity.xml b/app/src/main/res/layout/add_device_activity.xml index 8ff8b1c..0f75742 100644 --- a/app/src/main/res/layout/add_device_activity.xml +++ b/app/src/main/res/layout/add_device_activity.xml @@ -5,6 +5,127 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/white" tools:context=".home.AddDeviceActivity"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/add_family_activity.xml b/app/src/main/res/layout/add_family_activity.xml new file mode 100644 index 0000000..9a0ae7d --- /dev/null +++ b/app/src/main/res/layout/add_family_activity.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/home_menu_fragment.xml b/app/src/main/res/layout/home_menu_fragment.xml index bfebc08..367263b 100644 --- a/app/src/main/res/layout/home_menu_fragment.xml +++ b/app/src/main/res/layout/home_menu_fragment.xml @@ -77,6 +77,7 @@ + android:background="@drawable/bg_white" + android:layout_marginBottom="14dp" + android:layout_gravity="center_horizontal" + android:padding="8dp"> - - + android:layout_height="80dp" + android:layout_weight="1" + android:scaleType="centerInside" + android:src="@mipmap/ic_launcher_round" /> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/go_up" /> - + android:layout_marginTop="4dp" + android:textColor="@color/black" + android:textSize="12dp" /> - + - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_device2.xml b/app/src/main/res/layout/item_device2.xml new file mode 100644 index 0000000..4860241 --- /dev/null +++ b/app/src/main/res/layout/item_device2.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/personal_profile_activity.xml b/app/src/main/res/layout/personal_profile_activity.xml index 0d4435e..cd1b63a 100644 --- a/app/src/main/res/layout/personal_profile_activity.xml +++ b/app/src/main/res/layout/personal_profile_activity.xml @@ -5,7 +5,7 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@color/message_bg" + android:background="@color/white" android:orientation="vertical" tools:context=".personal.PersonalProfileActivity"> @@ -47,22 +47,20 @@ android:id="@+id/ivAvatar" android:layout_width="112dp" android:layout_height="112dp" - android:padding="2dp" - android:src="@mipmap/ic_launcher_round" /> + android:src="@mipmap/ic_launcher_round"/> + android:layout_marginEnd="5dp"> @@ -78,6 +76,7 @@ android:id="@+id/itemNickname" android:layout_width="match_parent" android:layout_height="60dp" + android:background="@color/white" android:gravity="center_vertical" android:orientation="horizontal" android:paddingHorizontal="16dp"> @@ -120,6 +119,7 @@ android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginTop="8dp" + android:background="@color/white" android:gravity="center_vertical" android:orientation="horizontal" android:paddingHorizontal="16dp"> @@ -132,7 +132,7 @@ android:textSize="16dp" /> + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file