main
杨万里 2 months ago
parent 2ad238ff63
commit b5ad951171

3
.idea/.gitignore vendored

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

@ -5,6 +5,9 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:name=".MyApplication"
@ -15,38 +18,79 @@
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity2">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
</activity>
<activity
android:name=".TyreLayoutActivity"
android:exported="false" />
<activity
android:name=".TestActivity"
android:exported="false"
android:label="@string/title_activity_test"
android:theme="@style/AppTheme.NoActionBar">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.MAIN" /> -->
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
<!-- </intent-filter> -->
</activity>
<activity android:name=".HomePageActivity">
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.MAIN" />-->
<activity
android:name=".HomePageActivity"
android:exported="false">
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
<!-- </intent-filter>-->
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.MAIN" /> -->
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
<!-- </intent-filter> -->
</activity>
<activity android:name=".TyreSearchActivity" />
<activity android:name=".MainActivity">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OutStoreHouseActivity" />
<activity android:name=".CheckActivity" />
<activity android:name=".InStoreHouseActivity" />
<activity android:name=".TyreLoadUnLoadActivity" />
<activity android:name=".UpActivity" />
<activity android:name=".DownActivity" />
<activity android:name=".SwitchActivity" />
<activity
android:name=".OutStoreHouseActivity"
android:exported="false" />
<activity
android:name=".CheckActivity"
android:exported="false" />
<activity
android:name=".InStoreHouseActivity"
android:exported="false" />
<activity
android:name=".TyreLoadUnLoadActivity"
android:exported="false" />
<activity
android:name=".UpActivity"
android:exported="false" />
<activity
android:name=".DownActivity"
android:exported="false" />
<activity
android:name=".SwitchActivity"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

@ -25,13 +25,17 @@ import com.android.hdhe.uhf.readerInterface.TagModel;
import com.example.tyre.entity.AjaxResult;
import com.example.tyre.entity.BaseTyre;
import com.example.tyre.entity.Check;
import com.example.tyre.entity.CheckInfoSpinnerVo;
import com.example.tyre.entity.EPC;
import com.example.tyre.entity.InStoreSpinnerVo;
import com.example.tyre.entity.Tyre;
import com.example.tyre.util.CommonDialog;
import com.example.tyre.util.MyUrl;
import com.example.tyre.util.PlayMusic;
import com.example.tyre.util.SharedPreferencesUtils;
import com.example.tyre.util.Util;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
@ -51,22 +55,23 @@ import butterknife.OnClick;
import cn.pda.serialport.Tools;
public class CheckActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
@BindView(R.id.epc)
TextView Epc;
@BindView(R.id.checkresult)
TextView checkresult;
@BindView(R.id.tyrecon)
TextView tyrecon;
@BindView(R.id.th)
TextView th;
@BindView(R.id.zbh)
TextView zbh;
@BindView(R.id.result)
Spinner result;
@BindView(R.id.wc)
Button wc;
@BindView(R.id.fh)
Button fh;
@BindView(R.id.epc_display) TextInputEditText epcInput;
@BindView(R.id.th) TextInputEditText tyreNoInput;
@BindView(R.id.zbh) TextInputEditText selfNoInput;
@BindView(R.id.tyrecon) TextInputEditText remarkInput;
@BindView(R.id.patternDepth) TextInputEditText patternDepthInput;
@BindView(R.id.mileage) TextInputEditText mileageInput;
@BindView(R.id.epc_layout) TextInputLayout epcLayout;
@BindView(R.id.th_layout) TextInputLayout tyreNoLayout;
@BindView(R.id.zbh_layout) TextInputLayout selfNoLayout;
@BindView(R.id.mileage_layout) TextInputLayout mileageNoLayout;
@BindView(R.id.patternDepth_layout) TextInputLayout patternDepthNoLayout;
@BindView(R.id.result) Spinner resultSpinner;
@BindView(R.id.CheckTypeSpinner) Spinner checkTypeSpinner;
private boolean isStart = true;
private ProgressDialog progressDialog;
private boolean runFlag = true;
@ -90,7 +95,8 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
Thread thread = new InventoryThread();
thread.start();
Util.initSoundPool(this);
result.setOnItemSelectedListener(this);
resultSpinner.setOnItemSelectedListener(this);
checkTypeSpinner.setOnItemSelectedListener(this);
check_spinner();
showLoadingDialog();
}
@ -198,16 +204,21 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
nextTime = lastTime;
Log.e("TAG", "run: " + time);
}
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
String currentEpc = listepc.get(0);
epcInput.setText(currentEpc);
//请求后台
debounceHandler.removeMessages(1);
lastScannedEpc = currentEpc;
debounceHandler.sendEmptyMessageDelayed(1, DEBOUNCE_DELAY);
// showLoadingDialog();
// find(listepc.get(0).toString());
}
clearData();
}
});
Log.e("EPC", "listepc:+ " + listepc);
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
Epc.setText(listepc.get(0).toString());
//请求后台
find(listepc.get(0).toString());
}
clearData();
}
private void clearData() {
listEPC.removeAll(listEPC);
@ -267,7 +278,10 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (parent.getId()) {
case R.id.result:
checkresult.setText(parent.getItemAtPosition(position).toString());
// checkresult.setText(parent.getItemAtPosition(position).toString());
break;
case R.id.CheckTypeSpinner:
// checktype.setText(parent.getItemAtPosition(position).toString());
break;
}
@ -282,16 +296,31 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.wc:
String rfid=Epc.getText().toString();
String result = checkresult.getText().toString();
String remark = tyrecon.getText().toString();
if (rfid == null || rfid.isEmpty())
String rfid=epcInput.getText().toString();
String selectedResult = resultSpinner.getSelectedItem().toString();
String checkType = checkTypeSpinner.getSelectedItem().toString();
String remark = remarkInput.getText().toString();
String mileage = mileageInput.getText().toString().trim();
String patternDepth = patternDepthInput.getText().toString().trim();
String tyreNo = tyreNoInput.getText().toString().trim();
String selfNo = selfNoInput.getText().toString().trim();
if (rfid == null || rfid.isEmpty() || rfid.equals("等待扫描..."))
{
new CommonDialog(CheckActivity.this).setMessage("请扫描轮胎!").show();
epcLayout.setError("请扫描芯片");
return;
}
showLoadingDialog();
insert_check_record(rfid,result,remark);
if (tyreNo == null || tyreNo.isEmpty())
{
tyreNoLayout.setError("请检查胎号数据");
return;
}
if (selfNo == null || selfNo.isEmpty())
{
selfNoLayout.setError("请检查自编号数据");
return;
}
showLoadingDialog();
insert_check_record(rfid,selectedResult,remark,checkType,mileage,patternDepth);
break;
case R.id.fh:
Intent intent=new Intent(this,HomePageActivity.class);
@ -300,16 +329,32 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
}
}
// 防抖延迟时间 (毫秒)
private static final long DEBOUNCE_DELAY = 500;
// 用于存储最后一次扫描到的 EPC
private String lastScannedEpc;
// 用于处理防抖逻辑的 Handler
private Handler debounceHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 1 && lastScannedEpc != null) {
// 延迟时间到,执行查询
showLoadingDialog();
performFind(lastScannedEpc);
lastScannedEpc = null; // 清空,等待下一次扫描
}
return true;
}
});
// 基本信息查询
private void find(String epc) {
private void performFind(String epc) {
OkGo.<String>post(MyUrl.url + "/tyre/tyre/pdaQueryTyreInfo").tag(this).params("tyreEpc", epc)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
String body = response.body();
hideLoadingDialog();
try {
Gson gson = new Gson();
BaseTyre baseTyre = gson.fromJson(body, BaseTyre.class);
@ -317,12 +362,12 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
// 空值处理:若字段为 null 则显示空字符串
String TyreNo = safeGetString(baseTyre.getTyreNo());
String zb = safeGetString(baseTyre.getSelfNo());
th.setText(TyreNo);
zbh.setText(zb);
tyreNoInput.setText(TyreNo);
selfNoInput.setText(zb);
}else {
new CommonDialog(CheckActivity.this).setMessage("系统无此轮胎!").show();
th.setText("");
zbh.setText("");
tyreNoInput.setText("");
selfNoInput.setText("");
}
} catch (JsonSyntaxException e) {
return;
@ -335,37 +380,56 @@ public class CheckActivity extends AppCompatActivity implements AdapterView.OnIt
return value == null || "null".equals(value) ? "" : value;
}
private void check_spinner() {
OkGo.<String>post(MyUrl.url + "/system/dict/data//checkResultList").execute(new StringCallback() {
OkGo.<String>post(MyUrl.url + "/system/dict/data/getDictDataList").execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
String body = response.body();
Gson gson = new Gson();
hideLoadingDialog();
List<String> stringList =new ArrayList<>();
stringList = gson.fromJson(body, new TypeToken<List<String>>() {
}.getType());
CheckInfoSpinnerVo checkInfoSpinnerVo =new CheckInfoSpinnerVo();
checkInfoSpinnerVo = gson.fromJson(body,CheckInfoSpinnerVo.class);
List<String> stringList=checkInfoSpinnerVo.getCheckResultList();
List<String> checkTypeList=checkInfoSpinnerVo.getCheckTypeList();
// List<String> stringList =new ArrayList<>();
// stringList = gson.fromJson(body, new TypeToken<List<String>>() {
// }.getType());
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(CheckActivity.this, android.R.layout.simple_list_item_1, stringList);
result.setAdapter(arrayAdapter);
}
});
result.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
checkresult.setText(parent.getItemAtPosition(position).toString());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
resultSpinner.setAdapter(arrayAdapter);
ArrayAdapter<String> checkTypeAdapter = new ArrayAdapter<>(CheckActivity.this, android.R.layout.simple_list_item_1, checkTypeList);
checkTypeSpinner.setAdapter(checkTypeAdapter);
}
});
// result.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
// @Override
// public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// //checkresult.setText(parent.getItemAtPosition(position).toString());
// }
//
// @Override
// public void onNothingSelected(AdapterView<?> parent) {
// }
// });
// result.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
// @Override
// public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// // checktype.setText(parent.getItemAtPosition(position).toString());
// }
//
// @Override
// public void onNothingSelected(AdapterView<?> parent) {
// }
// });
}
//插质检记录表
private void insert_check_record(String rfid,String result,String remark){
private void insert_check_record(String rfid,String selectedResult,String remark,String checkType,String mileage,String patternDepth){
OkGo.<String>post(MyUrl.url + "/tyre/check/PdaAddCheck")
.params("tyreRfid",rfid)
.params("result",result)
.params("result",selectedResult)
.params("remark",remark)
.params("maintenanceType",checkType)
.params("mileage",mileage)
.params("patternDepth",patternDepth)
.params("CreateBy", SharedPreferencesUtils.getstring("user","admin"))
.execute(new StringCallback() {
@Override

@ -69,6 +69,8 @@ public class DownActivity extends AppCompatActivity implements AdapterView.OnIte
TextView th;
@BindView(R.id.zbh)
TextView zbh;
@BindView(R.id.patternDepth)
EditText patternDepth;
private boolean isStart = true;
private ProgressDialog progressDialog;
private boolean runFlag = true;
@ -270,6 +272,7 @@ public class DownActivity extends AppCompatActivity implements AdapterView.OnIte
String carNo = car.getText().toString();
String millage = start.getText().toString();
String wheel = azlw.getText().toString();
String depth = patternDepth.getText().toString();
if (rfid == null || rfid.isEmpty())
{
new CommonDialog(DownActivity.this).setMessage("请扫描轮胎!").show();
@ -291,7 +294,7 @@ public class DownActivity extends AppCompatActivity implements AdapterView.OnIte
return;
}
showLoadingDialog();
down_insert(rfid,carNo,millage,wheel);
down_insert(rfid,carNo,millage,wheel,depth);
break;
case R.id.back:
Intent intent = new Intent(this, HomePageActivity.class);
@ -346,12 +349,13 @@ public class DownActivity extends AppCompatActivity implements AdapterView.OnIte
return value == null || "null".equals(value) ? "" : value;
}
// 删除实时表、卸车记录表
private void down_insert(String rfid,String carNo,String millage,String wheel) {
private void down_insert(String rfid,String carNo,String millage,String wheel,String patternDepth) {
OkGo.<String>post(MyUrl.url + "/tyre/install/PdaUnInstallTyre").tag(this)
.params("tyreRfid", rfid)
.params("mileage", millage)
.params("carNo", carNo)
.params("wheelPostion", wheel)
.params("patternDepth", patternDepth)
.params("CreateBy", SharedPreferencesUtils.getstring("user","admin"))
.execute(new StringCallback() {
@Override

@ -33,66 +33,94 @@ public class HomePageActivity extends AppCompatActivity {
RadioButton zhijian;
@BindView(R.id.logout)
Button logout;
private long exitTime=0;
@Override
private long exitTime = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homepage);
ButterKnife.bind(this);
}
@OnClick({R.id.chaxun, R.id.ruku, R.id.chuku, R.id.zhuangxie, R.id.huanwei,R.id.zhijian,R.id.xxbd})
/**
* 1 R.id.logout
*/
@OnClick({R.id.chaxun, R.id.ruku, R.id.chuku, R.id.zhuangxie, R.id.huanwei, R.id.zhijian, R.id.xxbd,R.id.test1, R.id.logout})
public void onViewClicked(View view) {
Intent intent = new Intent(this,MainActivity.class);
Intent intent; // 建议在这里声明,而不是方法最开始
switch (view.getId()) {
case R.id.chaxun:
intent=new Intent(this,TyreSearchActivity.class);
intent = new Intent(this, TyreSearchActivity.class);
break;
case R.id.ruku:
intent=new Intent(this,InStoreHouseActivity.class);
intent = new Intent(this, InStoreHouseActivity.class);
break;
case R.id.chuku:
intent=new Intent(this,OutStoreHouseActivity.class);
intent = new Intent(this, OutStoreHouseActivity.class);
break;
case R.id.zhuangxie:
intent=new Intent(this,UpActivity.class);
intent = new Intent(this, UpActivity.class);
break;
case R.id.huanwei:
intent=new Intent(this,DownActivity.class);
intent = new Intent(this, DownActivity.class);
break;
case R.id.zhijian:
intent=new Intent(this,CheckActivity.class);
break;
case R.id.logout:
finish();
intent = new Intent(this, CheckActivity.class);
break;
case R.id.xxbd:
intent=new Intent(this,TestActivity.class);
intent = new Intent(this, TestActivity.class);
break;
case R.id.test1:
intent = new Intent(this, TyreLayoutActivity.class);
break;
case R.id.logout:
// 修改点 2处理退出逻辑
handleLogout();
return; // 退出后直接返回,不需要执行下面的 startActivity
default:
return;
}
// 只有非退出按钮才执行跳转
startActivity(intent);
}
/**
* 退
*/
private void handleLogout() {
// 1. 清除登录状态(可选:清除 SharedPreferences 中的用户信息)
// 例如SharedPreferencesUtils.clear();
// 2. 提示用户
Toast.makeText(this, "已退出登录", Toast.LENGTH_SHORT).show();
// 3. 跳转回登录页 (MainActivity)
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
// 4. 关闭当前主页,防止按返回键回到主页
finish();
}
private void exit() {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
finish();
// System.exit(0); // 通常不需要手动调用 System.exitfinish() 即可
}
else{
finish();
System.exit(0);
}
}
}
@Override
public boolean onKeyDown(int keyCode,KeyEvent event){
if(keyCode== KeyEvent.KEYCODE_BACK){
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
exit();
return false;
}
return super.onKeyDown(keyCode,event);
return super.onKeyDown(keyCode, event);
}
}
}

@ -69,6 +69,8 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
TextView cengji;
@BindView(R.id.huawen)
TextView huawen;
@BindView(R.id.gcts)
TextView gcts;
@BindView(R.id.back)
Button back;
@BindView(R.id.wtbm)
@ -97,6 +99,9 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
@BindView(R.id.spinnerBrand)
Spinner spinnerBrand;
@BindView(R.id.spinnergcts)
Spinner spinnergcts;
// private UHFService mDevice;
// private MyHandler handler;
private boolean isStart = true;
@ -119,6 +124,7 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
spinnerlevel.setOnItemSelectedListener(this);
spinnerSize.setOnItemSelectedListener(this);
spinnerBrand.setOnItemSelectedListener(this);
spinnergcts.setOnItemSelectedListener(this);
initView();
Thread thread = new InventoryThread();
thread.start();
@ -249,17 +255,24 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
nextTime = lastTime;
Log.e("TAG", "run: " + time);
}
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
String currentEpc = listepc.get(0);
scan.setText(currentEpc);
}
clearData();
}
});
Log.e("EPC", "listepc:+ " + listepc);
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
// scan.setText("测试");
scan.setText(listepc.get(0).toString());
//请求后台
//find(listepc.get(0).toString());
}
clearData();
// if (listepc != null && !listepc.isEmpty()){
// startFlag = false;
//// scan.setText("测试");
// scan.setText(listepc.get(0).toString());
// //请求后台
// find(listepc.get(0).toString());
// }
// clearData();
}
private void clearData() {
listEPC.removeAll(listEPC);
@ -279,6 +292,8 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
BaseTyre baseTyre = gson.fromJson(body, BaseTyre.class);
if (baseTyre != null) {
// 空值处理:若字段为 null 则显示空字符串
String tyreNo = safeGetString(baseTyre.getTyreNo());
wtbm.setText(tyreNo);
String brand = safeGetString(baseTyre.getTyreBrand());
String model = safeGetString(baseTyre.getTyreModel());
String level = safeGetString(baseTyre.getTyreLevel());
@ -300,7 +315,7 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
return value == null || "null".equals(value) ? "" : value;
}
//添加到库存表
private void insert_inventory(String epc,String wtbm,String pinpai,String xinghao,String cengji,String huawen,String tyrekind) {
private void insert_inventory(String epc,String wtbm,String pinpai,String xinghao,String cengji,String huawen,String grooves,String tyrekind) {
OkGo.<String>post(MyUrl.url + "/tyre/inventory/pdaAddInventory").tag(this)
.params("tyreRfid", epc)
.params("tyreEpc",epc)
@ -309,6 +324,7 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
.params("tyreModel",xinghao)
.params("tyreLevel",cengji)
.params("tyrePattern",huawen)
.params("grooves",grooves)
.params("tyreType",tyrekind)
.params("CreateBy",SharedPreferencesUtils.getstring("user","admin")).execute(new StringCallback() {
@Override
@ -319,6 +335,11 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
AjaxResult ajaxResult = gson.fromJson(body, AjaxResult.class);
handleResponse(ajaxResult);
}
@Override
public void onError(Response<String> response) {
hideLoadingDialog();
Toast.makeText(InStoreHouseActivity.this, "请求失败,请检查网络或重试", Toast.LENGTH_SHORT).show();
}
});
}
private void handleResponse(AjaxResult result) {
@ -348,12 +369,13 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
String c=cengji.getText().toString();
String h=huawen.getText().toString();
String t=tyrekind.getText().toString();
String g=gcts.getText().toString();
if (scan.getText().toString()==""){
new CommonDialog(InStoreHouseActivity.this).setMessage("请扫描轮胎芯片!").show();
return;
}
showLoadingDialog();
insert_inventory(epc,w,p,x,c,h,t);
insert_inventory(epc,w,p,x,c,h,g,t);
// }
break;
case R.id.back:
@ -385,6 +407,9 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
case R.id.spinnerBrand:
pinpai.setText(parent.getItemAtPosition(position).toString());
break;
case R.id.spinnergcts:
gcts.setText(parent.getItemAtPosition(position).toString());
break;
}
}
private Toast mToast;
@ -438,17 +463,19 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
List<String> patternLevel=inStoreSpinnerVo.getLevelList();
List<String> patternSize=inStoreSpinnerVo.getTyreSizeList();
List<String> patternBrand=inStoreSpinnerVo.getTyreBrandList();
List<String> patternGcts=inStoreSpinnerVo.getGctsList();
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(InStoreHouseActivity.this, android.R.layout.simple_list_item_1, stringList);
ArrayAdapter<String> arrayAdapterPattern = new ArrayAdapter<>(InStoreHouseActivity.this, android.R.layout.simple_list_item_1, patternList);
ArrayAdapter<String> arrayAdapterLevel = new ArrayAdapter<>(InStoreHouseActivity.this, android.R.layout.simple_list_item_1, patternLevel);
ArrayAdapter<String> arrayAdapterSize = new ArrayAdapter<>(InStoreHouseActivity.this, android.R.layout.simple_list_item_1, patternSize);
ArrayAdapter<String> arrayAdapterBrand = new ArrayAdapter<>(InStoreHouseActivity.this, android.R.layout.simple_list_item_1, patternBrand);
ArrayAdapter<String> arrayAdapterGcts = new ArrayAdapter<>(InStoreHouseActivity.this, android.R.layout.simple_list_item_1, patternGcts);
spinnerkind.setAdapter(arrayAdapter);
spinnerpattern.setAdapter(arrayAdapterPattern);
spinnerlevel.setAdapter(arrayAdapterLevel);
spinnerSize.setAdapter(arrayAdapterSize);
spinnerBrand.setAdapter(arrayAdapterBrand);
spinnergcts.setAdapter(arrayAdapterGcts);
}
});
spinnerkind.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@ -501,7 +528,16 @@ public class InStoreHouseActivity extends AppCompatActivity implements AdapterVi
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinnergcts.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
gcts.setText(parent.getItemAtPosition(position).toString());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
private KeyReceiver keyReceiver;
private void registerReceiver() {

@ -1,29 +1,55 @@
package com.example.tyre;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.util.Log;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListPopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import com.example.tyre.entity.AjaxResult;
import com.example.tyre.entity.Tyre;
import com.example.tyre.util.CommonDialog;
import com.example.tyre.util.MyUrl;
import com.example.tyre.util.SharedPreferencesUtils;
import com.google.gson.Gson;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.FileCallback;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Progress;
import com.lzy.okgo.model.Response;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import org.json.JSONObject;
import java.io.File;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
//implements OnTouchListener,OnItemClickListener
public class MainActivity extends AppCompatActivity {
@BindView(R.id.login_name)
EditText loginName;
@ -31,54 +57,190 @@ public class MainActivity extends AppCompatActivity {
EditText loginPass;
@BindView(R.id.login_log)
Button loginLog;
private EditText etTest;
private ListPopupWindow lpw;
private String[] list;
@BindView(R.id.checkbox_remember)
CheckBox cbRemember;
@BindView(R.id.version)
TextView version;
// 声明进度条变量
private ProgressDialog progressDialog;
private static final int PERMISSION_REQUEST_CODE = 1001;
private BroadcastReceiver downloadReceiver;
private static final int REQUEST_PERMISSIONS = 100;
private long downloadId;
private DownloadManager downloadManager;
private String newVersionName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
loginName.setText("admin");
loginPass.setText("haiwei@123");
// etTest = (EditText) findViewById(R.id.login_name);
// etTest.setOnTouchListener(this);
// list = new String[] { "item1", "item2", "item3", "item4" };
// lpw = new ListPopupWindow(this);
// lpw.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, list));
// lpw.setAnchorView(etTest);
// lpw.setModal(true);
// lpw.setOnItemClickListener(this);
// --- 新增:页面加载时读取保存的账号密码 ---
initRememberInfo();
// 2. 检查权限并开始检查更新
//showLoadingDialog();
//checkPermissionsAndUpdate();
// 注册下载完成广播接收器
//registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
/**
*
*/
private void checkPermissionsAndUpdate() {
// Android 6.0+ 动态申请存储权限用于下载APK
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
} else {
// 权限已获取,开始检查更新
checkAppUpdate();
}
} else {
// 版本低于 6.0,直接检查更新
checkAppUpdate();
}
}
/**
*
*/
private void initRememberInfo() {
// 假设你在 SharedPreferencesUtils 中保存的 key 是 "user" 和 "password"
String savedUser = SharedPreferencesUtils.getstring("user", "");
String savedPass = SharedPreferencesUtils.getstring("password", "");
// 如果用户名不为空说明之前勾选过则填充数据并勾选CheckBox
if (savedUser != null && !savedUser.isEmpty()) {
loginName.setText(savedUser);
loginPass.setText(savedPass);
cbRemember.setChecked(true);
} else {
cbRemember.setChecked(false);
}
}
@OnClick(R.id.login_log)
public void onViewClicked() {
showLoadingDialog();
login(loginName.getText().toString(),loginPass.getText().toString());
}
// @Override
// public void onItemClick(AdapterView<?> parent, View view, int position,long id) {String item = list[position];etTest.setText(item);lpw.dismiss();
// }
// @Override
// public boolean onTouch(View v, MotionEvent event) {final int DRAWABLE_RIGHT = 2;
// if (event.getAction() == MotionEvent.ACTION_UP) {if (event.getX() >= (v.getWidth() - ((EditText) v) .getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {lpw.show();return true;
// }
// }
// return false;
// }
private void showLoadingDialog() {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("数据加载中...");
progressDialog.setCancelable(false);
progressDialog.show();
}
private void hideLoadingDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
// 获取输入内容
String name = loginName.getText().toString().trim();
String pass = loginPass.getText().toString().trim();
// --- 修改在点击登录时立即获取CheckBox状态 ---
// 注意:这里直接用 cbRemember.isChecked(),不要等到网络请求回来再判断
boolean isRemember = cbRemember.isChecked();
// 简单的非空校验
if (name.isEmpty() || pass.isEmpty()) {
Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
return;
}
showLoadingDialog();
login(name, pass, isRemember); // 将状态传递给 login 方法
}
private void login(String name, String pass) {
/**
*
*/
private void checkAppUpdate() {
// 1. 获取本地版本号 (从 AndroidManifest.xml 读取)
String localVersionName = getVersionName();
Log.d("Version", "本地版本: " + localVersionName);
// 2. 请求服务器接口获取最新版本
// 假设接口返回格式: { "code": "0", "data": { "versionCode": 2, "apkUrl": "..." } }
OkGo.<String>post(MyUrl.url + "/system/package/checkUpdate") // 替换为你实际的检查更新接口地址
.tag(this)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
hideLoadingDialog();
try {
JSONObject jsonObject = new JSONObject(response.body());
String code = jsonObject.getString("code");
if ("0".equals(code)) {
JSONObject data = jsonObject.getJSONObject("data");
// // 获取服务器版本号 (String)
String serverVersionName = data.getString("version");
String apkUrl = data.getString("fileName");
int compareResult = compareVersion(serverVersionName, localVersionName);
runOnUiThread(() -> {
version.setText("当前版本: " + localVersionName + " | 最新版本: " + serverVersionName);
});
// // 3. 对比版本号
// // 如果服务器版本 > 本地版本
if (compareResult > 0) {
showUpdateDialog(apkUrl, serverVersionName);
}
// if (compareVersion(serverVersionName, localVersionName) > 0) {
// showUpdateDialog(apkUrl);
// }
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
*
*/
private void showUpdateDialog(String downloadUrl, String serverVersion) {
this.newVersionName = serverVersion;
new AlertDialog.Builder(this)
.setTitle("发现新版本 " + serverVersion)
.setMessage("检测到最新版本,是否立即下载并安装?")
.setPositiveButton("立即下载", (dialog, which) -> startDownload(downloadUrl))
.setNegativeButton("取消", null)
.show();
}
private String getVersionName() {
// 1. 先尝试从 SP 读取(这个值是上次下载更新时存进去的最新版本)
// 3. 如果 SP 里没有(说明是第一次安装或没更新过),读取 build.gradle 里的 versionName
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return "1.0";
}
private int compareVersion(String v1, String v2) {
// 如果两个版本号完全相同直接返回0
if (v1.equals(v2)) {
return 0;
}
// 将版本号按 "." 分割成数组
String[] v1Array = v1.split("\\.");
String[] v2Array = v2.split("\\.");
// 获取最大长度,确保能遍历完所有部分
int maxLength = Math.max(v1Array.length, v2Array.length);
for (int i = 0; i < maxLength; i++) {
// 获取当前位的数值,如果该位置不存在(比如 1.0 对比 1.0.1),则默认为 0
int v1Part = i < v1Array.length ? Integer.parseInt(v1Array[i]) : 0;
int v2Part = i < v2Array.length ? Integer.parseInt(v2Array[i]) : 0;
// 逐位比较
if (v1Part > v2Part) {
return 1; // v1 大
} else if (v1Part < v2Part) {
return -1; // v2 大
}
}
return 0; // 相等
}
/**
*
* @param isRemember
*/
private void login(String name, String pass, boolean isRemember) {
OkGo.<String>post(MyUrl.url + "/PdaLogin")
.tag(this)
.params("username", name)
@ -90,9 +252,23 @@ public class MainActivity extends AppCompatActivity {
String body = response.body();
Gson gson = new Gson();
AjaxResult ajaxResult = gson.fromJson(body, AjaxResult.class);
// 处理登录结果
handleLoginResponse(ajaxResult);
SharedPreferencesUtils.putstring("user",name);
SharedPreferencesUtils.putstring("password",pass);
// --- 修改:在这里处理保存逻辑 ---
// 如果登录成功(假设 code 为 "0" 代表成功),且用户勾选了记住密码,则保存
// 如果用户没勾选,则清空保存的数据
if ("0".equals(ajaxResult.getCode())) {
if (isRemember) {
SharedPreferencesUtils.putstring("user", name);
SharedPreferencesUtils.putstring("password", pass);
} else {
// 如果没勾选,清除本地存储的密码(可选)
SharedPreferencesUtils.putstring("user", "");
SharedPreferencesUtils.putstring("password", "");
}
}
}
@Override
@ -103,11 +279,28 @@ public class MainActivity extends AppCompatActivity {
});
}
private void showLoadingDialog() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("数据加载中...");
progressDialog.setCancelable(false);
}
if (!progressDialog.isShowing()) {
progressDialog.show();
}
}
private void hideLoadingDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
private void handleLoginResponse(AjaxResult result) {
switch (result.getCode()) {
case "0":
// 登录成功
Toast.makeText(this, result.getMsg(), Toast.LENGTH_SHORT).show();
//SharedPreferencesUtils.putString("UserID", name);
Intent intent = new Intent(this, HomePageActivity.class);
startActivity(intent);
finish();
@ -120,4 +313,103 @@ public class MainActivity extends AppCompatActivity {
break;
}
}
}
/**
* APK
* @param fileName (: "app-release.apk" "resourceName")
*/
private void startDownload(String fileName) {
// 1. 构建完整的下载 URL
String downloadUrl = MyUrl.url + "/common/downloadApk?fileName=tyre_update.apk";
downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
request.setTitle("APK下载");
request.setDescription("正在下载更新...");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
request.setRequiresDeviceIdle(false);
request.setAllowedOverMetered(true);
request.setAllowedOverRoaming(true);
}
downloadId = downloadManager.enqueue(request);
Toast.makeText(this, "开始下载...", Toast.LENGTH_SHORT).show();
}
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downloadId == id) {
SharedPreferencesUtils.putstring("local_app_version", newVersionName);
runOnUiThread(() -> {
// 这里更新界面上的 TextView
version.setText("当前版本: " + newVersionName); // ⭐ 修改:直接显示新版本
});
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
String localUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
installApk(Uri.parse(localUri).getPath());
} else {
int reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON));
Toast.makeText(context, "下载失败,错误码: " + reason, Toast.LENGTH_SHORT).show();
}
}
cursor.close();
}
}
};
private void installApk(String apkPath) {
File file = new File(apkPath);
if (!file.exists()) {
Toast.makeText(this, "APK文件不存在", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
uri = Uri.fromFile(file);
}
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (Exception e) {
Toast.makeText(this, "无法安装应用: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// unregisterReceiver(onDownloadComplete);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1001) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "已获得安装未知应用权限", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "未获得安装未知应用权限,无法自动安装", Toast.LENGTH_LONG).show();
}
}
}
}

@ -0,0 +1,189 @@
package com.example.tyre;
import android.Manifest;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import com.example.tyre.util.MyUrl;
import java.io.File;
public class MainActivity2 extends AppCompatActivity {
private static final int REQUEST_PERMISSIONS = 100;
private long downloadId;
private DownloadManager downloadManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Button downloadButton = findViewById(R.id.download_button);
// 注册下载完成广播接收器
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkPermissions()) {
startDownload("app-release.apk");
} else {
requestPermissions();
}
}
});
downloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checkPermissions()) {
startDownload("app-release.apk");
} else {
requestPermissions();
}
}
});
}
private boolean checkPermissions() {
boolean storagePermissionGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
boolean installPermissionGranted = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
installPermissionGranted = getPackageManager().canRequestPackageInstalls();
}
return storagePermissionGranted && installPermissionGranted;
}
private void requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_PERMISSIONS);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!getPackageManager().canRequestPackageInstalls()) {
startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
.setData(Uri.parse(String.format("package:%s", getPackageName()))), 1001);
}
}
}
/**
* APK
* @param fileName (: "app-release.apk" "resourceName")
*/
private void startDownload(String fileName) {
// 1. 构建完整的下载 URL
String downloadUrl = MyUrl.url + "/common/downloadApk?fileName=tyre_update.apk";
downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
request.setTitle("APK下载");
request.setDescription("正在下载更新...");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
request.setRequiresDeviceIdle(false);
request.setAllowedOverMetered(true);
request.setAllowedOverRoaming(true);
}
downloadId = downloadManager.enqueue(request);
Toast.makeText(this, "开始下载...", Toast.LENGTH_SHORT).show();
}
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downloadId == id) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
String localUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
installApk(Uri.parse(localUri).getPath());
} else {
int reason = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON));
Toast.makeText(context, "下载失败,错误码: " + reason, Toast.LENGTH_SHORT).show();
}
}
cursor.close();
}
}
};
private void installApk(String apkPath) {
File file = new File(apkPath);
if (!file.exists()) {
Toast.makeText(this, "APK文件不存在", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
uri = Uri.fromFile(file);
}
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (Exception e) {
Toast.makeText(this, "无法安装应用: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1001) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "已获得安装未知应用权限", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "未获得安装未知应用权限,无法自动安装", Toast.LENGTH_LONG).show();
}
}
}
}

@ -85,7 +85,7 @@ public class TestActivity extends AppCompatActivity {
private KeyReceiver keyReceiver;
private String deptId;
String min = "EC0001012026010100000001"; // 左边界(包含)
String max = "EC00010120260101001000000"; // 右边界(包含)
String max = "EC0001012026010100100000"; // 右边界(包含)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

@ -0,0 +1,507 @@
package com.example.tyre;
import androidx.appcompat.app.AppCompatActivity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.android.hdhe.uhf.reader.UhfReader;
import com.android.hdhe.uhf.readerInterface.TagModel;
import com.example.tyre.entity.AjaxResult;
import com.example.tyre.entity.BaseCar;
import com.example.tyre.entity.BaseTyre;
import com.example.tyre.entity.EPC;
import com.example.tyre.util.CarSelectionDialog;
import com.example.tyre.util.CommonDialog;
import com.example.tyre.util.MyUrl;
import com.example.tyre.util.SharedPreferencesUtils;
import com.example.tyre.util.Util;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.pda.serialport.Tools;
public class TyreLayoutActivity extends AppCompatActivity {
// 1. 使用 @BindView 绑定控件
// 注意:变量名可以自定义,但 ID 必须对应 XML 中的 id
@BindView(R.id.et_plate_number)
TextInputEditText etPlateNumber;
@BindView(R.id.btn_retrieve)
Button btnRetrieve; // 因为使用的是 MaterialButton这里类型要对应
@BindView(R.id.til_plate_number)
TextInputLayout tilPlateNumber;
private ProgressDialog progressDialog;
private boolean isStart = true;
private boolean runFlag = true;
private boolean startFlag = false;
private UhfReader manager; // UHF manager,UHF Operating handle
private ArrayList<EPC> listEPC;
private ArrayList<String> listepc = new ArrayList<String>();
long lastTime;
long nextTime;
private Toast mToast;
private Toast toast;
private KeyReceiver keyReceiver;
String min = "EC0001012026010100000001"; // 左边界(包含)
String max = "EC0001012026010100100000"; // 右边界(包含)
// 1. 定义数据模型类 (对应后台返回的字段)
public static class TireData {
public String position; // 轮位名称
public String brand; // 品牌
public String spec; // 规格
public String installDate; // 安装日期
public TireData(String position, String brand, String spec, String installDate) {
this.position = position;
this.brand = brand;
this.spec = spec;
this.installDate = installDate;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tyre_layout);
ButterKnife.bind(this);
manager = MyApplication.getManager();
listEPC = new ArrayList<EPC>();
Thread thread = new InventoryThread();
thread.start();
Util.initSoundPool(this);
tilPlateNumber = findViewById(R.id.til_plate_number);
etPlateNumber.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
// 核心代码:只要用户输入了内容,就清除错误提示
tilPlateNumber.setError(null);
// 可选:如果你使用了 errorEnabled="true",可能还需要调用下面这行来彻底清除空间占用
// tilPlateNumber.setErrorEnabled(false);
}
});
tilPlateNumber.setEndIconOnClickListener(v -> {
// 在这里处理搜索逻辑
String plateNumber = etPlateNumber.getText().toString().trim();
if (!plateNumber.isEmpty()) {
// 执行搜索
showLoadingDialog();
performSearch(plateNumber);
} else {
tilPlateNumber.setError("车牌号不能为空");
}
});
}
@Override
public void onResume() {
super.onResume();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
registerReceiver();
}
@Override
public void onPause() {
startFlag = false;
super.onPause();
unregisterReceiver();
}
@Override
protected void onDestroy() {
startFlag = false;
runFlag = false;
super.onDestroy();
}
private void performSearch(String carNo) {
OkGo.<String>post(MyUrl.url + "/tyre/car/PdaQueryCarList")
.tag(this).params("carNo", carNo)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
hideLoadingDialog();
String body = response.body();
Gson gson=new Gson();
List<BaseCar> baseCarList = gson.fromJson(body, new TypeToken<List<BaseCar>>(){}.getType());
Log.e("EPC", "listepc:+ " + baseCarList.size());
if (baseCarList!=null && baseCarList.size()>0){
List<String> carNoList = new ArrayList<>();
for (BaseCar car : baseCarList) {
carNoList.add(car.getCarNo());
}
// 显示自定义弹窗
showCarSelectionDialog(carNoList);
}
}
});
}
private void showCarSelectionDialog(List<String> carNoList) {
CarSelectionDialog dialog = new CarSelectionDialog(this, carNoList);
dialog.setOnCarSelectedListener(new CarSelectionDialog.OnCarSelectedListener() {
@Override
public void onCarSelected(String carNo) {
// 处理选中的车辆
etPlateNumber.setText(carNo);
}
});
dialog.show();
}
@OnClick({R.id.btn_retrieve})
public void onViewClicked(View view) {
String PlateNumber = etPlateNumber.getText().toString();
switch (view.getId()) {
case R.id.btn_retrieve:
if (PlateNumber == null || PlateNumber.isEmpty())
{
new CommonDialog(TyreLayoutActivity.this).setMessage("请输入车牌号!").show();
return;
}
carBangding(PlateNumber);
break;
}
}
//绑定车牌与RFID信息
private void carBangding(String PlateNumber) {
OkGo.<String>post(MyUrl.url + "/tyre/tyre/getCarBingTire")
.tag(this).params("carNo", PlateNumber)
.execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
//hideLoadingDialog();
String body = response.body();
Gson gson=new Gson();
// List<BaseTyre> baseTyreList = gson.fromJson(body, BaseTyre.class);
List<BaseTyre> baseTyreList = gson.fromJson(body, new com.google.gson.reflect.TypeToken<List<BaseTyre>>(){}.getType());
bindDataToViews(baseTyreList);
}
});
}
private void findCar(String carNumber) {
OkGo.<String>post(MyUrl.url + "/tyre/car/queryCarByRfid").tag(this).params("rfid", carNumber).execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
String body = response.body();
hideLoadingDialog();
try {
Gson gson = new Gson();
BaseCar baseCar = gson.fromJson(body, BaseCar.class);
if (baseCar != null) {
// 空值处理:若字段为 null 则显示空字符串
String carNo = safeGetString(baseCar.getCarNo());
etPlateNumber.setText(carNo);
}else {
new CommonDialog(TyreLayoutActivity.this).setMessage("请检查车辆芯片绑定数据!").show();
}
} catch (JsonSyntaxException e) {
return;
}
}
});
}
private String safeGetString(String value) {
return value == null || "null".equals(value) ? "" : value;
}
/**
* Include
*/
private void bindDataToViews(List<BaseTyre> dataList) {
if (dataList == null) return;
// 遍历列表,根据具体位置找到对应的 View
for (BaseTyre tyre : dataList) {
View targetView = null;
// 根据后端返回的位置字段判断要更新哪个布局
// 假设 tyre.getPosition() 返回 "LF" (左前), "RF" (右前) 等
String pos = tyre.getWheelPostion();
if ("左前轮".equals(pos) || "1".equals(pos)) {
targetView = findViewById(R.id.tire_left_front);
} else if ("右前轮".equals(pos) || "2".equals(pos)) {
targetView = findViewById(R.id.tire_right_front);
} else if ("左内轮".equals(pos)) {
targetView = findViewById(R.id.tire_middle_left);
}else if ("右内轮".equals(pos)) {
targetView = findViewById(R.id.tire_middle_right);
}else if ("左外轮".equals(pos)) {
targetView = findViewById(R.id.tire_bottom_left);
}else if ("右外轮".equals(pos)) {
targetView = findViewById(R.id.tire_bottom_right);
}
// ... 其他位置
if (targetView != null) {
updateTireView(targetView, tyre);
}
}
}
// private void bindDataToViews(List<BaseTyre> dataList) {
// // 假设 dataList.get(0) 是左前轮dataList.get(1) 是右前轮...
// // 请根据你实际的列表顺序调整索引
//
// if (dataList.size() >= 2) {
// // 绑定左前轮
// updateTireView(findViewById(R.id.tire_left_front), dataList.get(0));
//
// // 绑定右前轮
// updateTireView(findViewById(R.id.tire_right_front), dataList.get(1));
//
// // 绑定其他轮胎...
// // updateTireView(findViewById(R.id.tire_left_mid), dataList.get(2));
// }
// }
/**
* UI
* @param container include View
* @param data
*/
private void updateTireView(View container, BaseTyre data) {
if (container == null) return;
// 【关键点】:必须在 container 内部查找控件,而不是在 Activity 中直接查找
TextView tvBrand = container.findViewById(R.id.tv_brand);
TextView tvSpec = container.findViewById(R.id.tv_spec);
TextView tvSelfNo = container.findViewById(R.id.tv_self_no); // 或者是 tv_install_date
TextView tvDate = container.findViewById(R.id.tv_install_date); // 或者是 tv_install_date
// 设置数据
if (tvBrand != null) tvBrand.setText("品牌: " + data.getTyreBrand());
if (tvSpec != null) tvSpec.setText("规格: " + data.getTyreModel());
if (tvSelfNo != null) tvSelfNo.setText("自编号: " + data.getSelfNo());
if (tvDate != null) tvDate.setText("日期: " + data.getCreateTime());
}
private void addToList(final List<EPC> list, final String epc, final byte rssi) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// The epc for the first time
if (list.isEmpty()) {
EPC epcTag = new EPC();
epcTag.setEpc(epc);
epcTag.setCount(1);
epcTag.setRssi(rssi);
list.add(epcTag);
listepc.add(epc);
}else {
for (int i = 0; i < list.size(); i++) {
EPC mEPC = list.get(i);
// list contain this epc
if (epc.equals(mEPC.getEpc())) {
mEPC.setCount(mEPC.getCount() + 1);
mEPC.setRssi(rssi);
list.set(i, mEPC);
break;
} else if (i == (list.size() - 1)) {
// list doesn't contain this epc
EPC newEPC = new EPC();
newEPC.setEpc(epc);
newEPC.setCount(1);
newEPC.setRssi(rssi);
list.add(newEPC);
listepc.add(epc);
}
}
}
// play sound
lastTime = SystemClock.elapsedRealtime();
long time = lastTime - nextTime;
if (time >= 60) {
Util.play(1, 0);
nextTime = lastTime;
Log.e("TAG", "run: " + time);
}
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
String currentEpc = listepc.get(0);
if (isInRange(currentEpc, min, max)) {
//请求后台 查询车辆信息
// car.setText(currentEpc);
//请求后台
debounceHandler.removeMessages(1);
lastScannedEpc = currentEpc;
debounceHandler.sendEmptyMessageDelayed(1, DEBOUNCE_DELAY);
}
}
clearData();
}
});
Log.e("EPC", "listepc:+ " + listepc);
}
/**
*
* @param target
* @param min
* @param max
* @return true=false=
*/
public static boolean isInRange(String target, String min, String max) {
// 空值校验,避免空指针异常
if (target == null || min == null || max == null) {
return false;
}
// compareTo规则
// 1. 字符串相等返回0
// 2. 目标字符串 > 对比字符串 返回正数;
// 3. 目标字符串 < 对比字符串 返回负数。
// 因此target >= min 等价于 target.compareTo(min) >= 0
// target <= max 等价于 target.compareTo(max) <= 0。
return target.compareTo(min) >= 0 && target.compareTo(max) <= 0;
}
// 防抖延迟时间 (毫秒)
private static final long DEBOUNCE_DELAY = 500;
// 用于存储最后一次扫描到的 EPC
private String lastScannedEpc;
// 用于处理防抖逻辑的 Handler
private Handler debounceHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 1 && lastScannedEpc != null) {
// 延迟时间到,执行查询
showLoadingDialog();
//查询车辆数据方法
findCar(lastScannedEpc);
lastScannedEpc = null; // 清空,等待下一次扫描
}
return true;
}
});
private void clearData() {
listEPC.removeAll(listEPC);
listepc.removeAll(listepc);
}
private class KeyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int keyCode = intent.getIntExtra("keyCode", 0);
if (keyCode == 0) {
keyCode = intent.getIntExtra("keycode", 0);
}
boolean keyDown = intent.getBooleanExtra("keydown", false);
if (keyDown) {
if (toast == null) {
// toast = Toast.makeText(OutStoreHouseActivity.this, "KeyReceiver:keyCode = down" + keyCode, Toast.LENGTH_SHORT);
} else {
// toast.setText("KeyReceiver:keyCode = down" + keyCode);
}
// toast.show();
switch (keyCode) {
case KeyEvent.KEYCODE_F1:
case KeyEvent.KEYCODE_F2:
case KeyEvent.KEYCODE_F3:
case KeyEvent.KEYCODE_F4:
case KeyEvent.KEYCODE_F5:
//扫描
startFlag = true;
break;
}
}
}
}
private void registerReceiver() {
keyReceiver = new KeyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.rfid.FUN_KEY");
filter.addAction("android.intent.action.FUN_KEY");
registerReceiver(keyReceiver, filter);
}
private void unregisterReceiver() {
unregisterReceiver(keyReceiver);
}
class InventoryThread extends Thread {
private List<TagModel> tagList;
byte[] accessPassword = Tools.HexString2Bytes("00000000");
@Override
public void run() {
super.run();
while (runFlag) {
if (startFlag) {
tagList = manager.inventoryRealTime(); //实时盘存
if (tagList != null && !tagList.isEmpty()) {
//播放提示音
Util.play(1, 0);
for (TagModel tag : tagList) {
if (tag == null) {
String epcStr = "";
// String epcStr = new String(epc);
addToList(listEPC, epcStr, (byte) -1);
} else {
String epcStr = Tools.Bytes2HexString(tag.getmEpcBytes(), tag.getmEpcBytes().length);
// String epcStr = new String(epc);
byte rssi = tag.getmRssi();
addToList(listEPC, epcStr, rssi);
}
}
}
tagList = null;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
private void showLoadingDialog() {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("数据加载中...");
progressDialog.setCancelable(false);
progressDialog.show();
}
private void hideLoadingDialog() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}

@ -90,7 +90,8 @@ public class UpActivity extends AppCompatActivity implements AdapterView.OnItemS
private Toast mToast;
private Toast toast;
private KeyReceiver keyReceiver;
String min = "EC0001012026010100000001"; // 左边界(包含)
String max = "EC0001012026010100100000"; // 右边界(包含)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -217,17 +218,70 @@ public class UpActivity extends AppCompatActivity implements AdapterView.OnItemS
nextTime = lastTime;
Log.e("TAG", "run: " + time);
}
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
String currentEpc = listepc.get(0);
if (isInRange(currentEpc, min, max)) {
//请求后台 查询车辆信息
// car.setText(currentEpc);
//请求后台
}else {
EPC.setText(currentEpc);
//请求后台
debounceHandler.removeMessages(1);
}
debounceHandler.removeMessages(1);
lastScannedEpc = currentEpc;
debounceHandler.sendEmptyMessageDelayed(1, DEBOUNCE_DELAY);
}
clearData();
}
});
Log.e("EPC", "listepc:+ " + listepc);
if (listepc != null && !listepc.isEmpty()){
startFlag = false;
EPC.setText(listepc.get(0).toString());
//请求后台
find(listepc.get(0).toString());
}
clearData();
}
/**
*
* @param target
* @param min
* @param max
* @return true=false=
*/
public static boolean isInRange(String target, String min, String max) {
// 空值校验,避免空指针异常
if (target == null || min == null || max == null) {
return false;
}
// compareTo规则
// 1. 字符串相等返回0
// 2. 目标字符串 > 对比字符串 返回正数;
// 3. 目标字符串 < 对比字符串 返回负数。
// 因此target >= min 等价于 target.compareTo(min) >= 0
// target <= max 等价于 target.compareTo(max) <= 0。
return target.compareTo(min) >= 0 && target.compareTo(max) <= 0;
}
// 防抖延迟时间 (毫秒)
private static final long DEBOUNCE_DELAY = 500;
// 用于存储最后一次扫描到的 EPC
private String lastScannedEpc;
// 用于处理防抖逻辑的 Handler
private Handler debounceHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 1 && lastScannedEpc != null) {
// 延迟时间到,执行查询
showLoadingDialog();
if (isInRange(lastScannedEpc, min, max)){
//查询车辆数据方法
findCar(lastScannedEpc);
}else {
find(lastScannedEpc);
}
lastScannedEpc = null; // 清空,等待下一次扫描
}
return true;
}
});
private void clearData() {
listEPC.removeAll(listEPC);
listepc.removeAll(listepc);
@ -356,11 +410,35 @@ public class UpActivity extends AppCompatActivity implements AdapterView.OnItemS
}
}
// 基本信息查询
private void findCar(String carNumber) {
OkGo.<String>post(MyUrl.url + "/tyre/car/queryCarByRfid").tag(this).params("rfid", carNumber).execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
String body = response.body();
hideLoadingDialog();
try {
Gson gson = new Gson();
BaseCar baseCar = gson.fromJson(body, BaseCar.class);
if (baseCar != null) {
// 空值处理:若字段为 null 则显示空字符串
String carNo = safeGetString(baseCar.getCarNo());
car.setText(carNo);
}else {
new CommonDialog(UpActivity.this).setMessage("请检查车辆芯片绑定数据!").show();
}
} catch (JsonSyntaxException e) {
return;
}
}
});
}
// 基本信息查询
private void find(String epc) {
OkGo.<String>post(MyUrl.url + "/tyre/tyre/pdaQueryTyreInfo").tag(this).params("tyreEpc", epc).execute(new StringCallback() {
@Override
public void onSuccess(Response<String> response) {
String body = response.body();
hideLoadingDialog();
try {
Gson gson = new Gson();
BaseTyre baseTyre = gson.fromJson(body, BaseTyre.class);

@ -1,6 +1,7 @@
package com.example.tyre.entity;
import java.util.Date;
/**
* base_tyre
@ -47,6 +48,16 @@ public class BaseTyre
private String wheelPostion;
private String createTime;
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getSelfNo() {
return selfNo;
}

@ -0,0 +1,24 @@
package com.example.tyre.entity;
import java.util.List;
public class CheckInfoSpinnerVo {
private List<String> checkResultList;
private List<String> checkTypeList;
public List<String> getCheckResultList() {
return checkResultList;
}
public void setCheckResultList(List<String> checkResultList) {
this.checkResultList = checkResultList;
}
public List<String> getCheckTypeList() {
return checkTypeList;
}
public void setCheckTypeList(List<String> checkTypeList) {
this.checkTypeList = checkTypeList;
}
}

@ -8,6 +8,15 @@ public class InStoreSpinnerVo {
private List<String> levelList;
private List<String> patternList;
private List<String> kindList;
private List<String> gctsList;
public List<String> getGctsList() {
return gctsList;
}
public void setGctsList(List<String> gctsList) {
this.gctsList = gctsList;
}
public List<String> getTyreBrandList() {
return tyreBrandList;

@ -6,7 +6,7 @@ package com.example.tyre.util;
* @date: 2019-10-24 13:59
*/
public class MyUrl {
public static String url="http://10.11.187.77:8020";
// public static String url="http://www.qdhys.xyz:8020";
// public static String url="http://192.168.0.102:8020";
// public static String url="http://192.168.31.26:8020";
public static String url="http://www.qdhys.xyz:8020";
// public static String url="http://10.11.187.77:8020";
}

@ -0,0 +1,12 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFF"/>
<stroke
android:width="2dp"
android:color="#DDDDDD"/>
<padding
android:left="2dp"
android:top="2dp"
android:right="2dp"
android:bottom="2dp"/>
</shape>

@ -0,0 +1,68 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="200"
android:viewportHeight="200">
<!-- 1. 轮胎外圈 (黑色橡胶) -->
<!-- 这是轮胎花纹的底色 -->
<path
android:fillColor="#1A1A1A"
android:pathData="M100,100m-95,0a95,95 0,1 1,190 0a95,95 0,1 1,-190 0" />
<!-- 2. 轮胎花纹沟槽 (模拟俯视纹理) -->
<!-- 我们通过绘制多个“Y”字形或放射状线条来模拟花纹 -->
<!-- 沟槽 1 -->
<path
android:fillColor="#000000"
android:pathData="M100,30
L100,50
M80,45
L100,55
L120,45
M100,55
L100,70" />
<!-- 沟槽 2 (旋转90度) -->
<path
android:fillColor="#000000"
android:pathData="M170,100
L150,100
M155,80
L145,100
L155,120
M145,100
L130,100" />
<!-- 沟槽 3 (旋转45度) -->
<path
android:fillColor="#000000"
android:pathData="M150,50
L135,65
M140,55
L130,70
L120,60
M130,70
L115,85" />
<!-- 沟槽 4 (旋转-45度) -->
<path
android:fillColor="#000000"
android:pathData="M150,150
L135,135
M140,145
L130,130
L120,140
M130,130
L115,115" />
<!-- 3. 轮胎中心孔 (深色) -->
<!-- 模拟轮毂中心 -->
<path
android:fillColor="#333333"
android:pathData="M100,100m-15,0a15,15 0,1 1,30 0a15,15 0,1 1,-30 0" />
<!-- 4. 高光效果 (模拟橡胶反光) -->
<!-- 增加一点光泽感,让轮胎看起来不那么死板 -->
<path
android:fillColor="#33333333"
android:pathData="M100,100m-70,0a70,70 0,1 1,140 0a70,70 0,1 1,-140 0" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -1,234 +1,284 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView2"
style="@style/tablebarStyleTwo"
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="轮胎质检"
app:layout_constraintTop_toTopOf="parent" />
android:layout_height="match_parent"
android:background="#F5F5F5"> <!-- 浅灰色背景 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="EPC:" />
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/epc"
<!-- 顶部标题卡片 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:textSize="15sp"
android:textColor="@color/black"
android:background="@drawable/bg_santex_coppy"
android:gravity="center" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="胎号:" />
<TextView
android:id="@+id/th"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:textSize="15sp"
android:textColor="@color/black"
android:background="@drawable/bg_santex_coppy"
android:gravity="center" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="自编号:" />
<TextView
android:id="@+id/zbh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:textSize="15sp"
android:textColor="@color/black"
android:background="@drawable/bg_santex_coppy"
android:gravity="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="105dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="检查结果:" />
<TextView
android:id="@+id/checkresult"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:textSize="22sp"
android:textColor="@color/black"
android:background="@drawable/bg_santex_coppy"
android:gravity="center" />
<Spinner
android:id="@+id/result"
android:layout_width="30dp"
android:layout_height="match_parent"></Spinner>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout3"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="105dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="处理意见:" />
<EditText
android:id="@+id/tyrecon"
android:layout_width="256dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:background="@drawable/bg_santex_coppy"
app:cardCornerRadius="12dp"
app:cardElevation="4dp"
android:layout_marginBottom="16dp">
android:textColor="@color/black"
android:textSize="22sp"
android:inputType="textMultiLine"
android:minLines="3"
android:lines="5"
android:gravity="top|start"
android:padding="8dp"
android:scrollbars="vertical"
android:hint="请输入内容"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="轮胎质检"
android:textSize="20sp"
android:textStyle="bold"
android:background="?attr/colorPrimary"
android:textColor="@android:color/white" />
</com.google.android.material.card.MaterialCardView>
<!-- EPC 输入项 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/epc_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp"
android:enabled="false">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/epc_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
android:text="等待扫描..."
android:textSize="16sp"
android:textColor="@android:color/black"
android:background="@null"
android:enabled="false"
android:focusable="false"
android:cursorVisible="false" />/>
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 胎号 & 自编号 (并排显示) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginEnd="4dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/th_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/th"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="轮胎编号"
android:textSize="16sp"
android:enabled="false"
android:focusable="false"
android:cursorVisible="false" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginStart="4dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/zbh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/zbh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="自编号"
android:textSize="16sp"
android:enabled="false"
android:focusable="false"
android:cursorVisible="false" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- 花纹深度 & 里程 (并排显示) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginEnd="4dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/patternDepth_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/patternDepth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="花纹深度(毫米)"
android:inputType="numberDecimal"
android:textSize="16sp" />
<!-- 单位直接写在 Hint 或通过辅助文本显示 -->
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginStart="4dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/mileage_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/mileage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="当前里程(公里)"
android:inputType="number"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- 检查结果 (下拉选择) -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/result_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp">
<Spinner
android:id="@+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/check_type_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp">
<Spinner
android:id="@+id/CheckTypeSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 处理意见 (多行文本) -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
android:layout_marginBottom="8dp">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_margin="8dp"
app:boxStrokeColor="?attr/colorPrimary">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/tyrecon"
android:layout_width="match_parent"
android:layout_height="120dp"
android:gravity="top|start"
android:hint="详细处理意见..."
android:inputType="textMultiLine"
android:maxLines="5"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 操作按钮 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="24dp"
android:gravity="center">
<Button
android:id="@+id/wc"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="8dp"
android:text="保存并完成"
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
<Button
android:id="@+id/fh"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="8dp"
android:text="返回重填"
style="@style/Widget.MaterialComponents.Button.TextButton" />
</LinearLayout>
</LinearLayout>
<!--<LinearLayout-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="40dp"-->
<!--android:layout_marginStart="8dp"-->
<!--android:layout_marginTop="20dp"-->
<!--android:layout_marginEnd="8dp"-->
<!--android:orientation="horizontal"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--app:layout_constraintTop_toBottomOf="@+id/linearLayout3">-->
<!--<TextView-->
<!--style="@style/alltext"-->
<!--android:layout_width="80dp"-->
<!--android:layout_height="match_parent"-->
<!--android:background="@color/blue2"-->
<!--android:text="操作人:" />-->
<!--<TextView-->
<!--android:id="@+id/czr"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:layout_marginStart="8dp"-->
<!--android:layout_weight="1"-->
<!--android:textSize="22sp"-->
<!--android:textColor="@color/black"-->
<!--android:background="@drawable/bg_santex_coppy"-->
<!--android:gravity="center" />-->
<!--<Spinner-->
<!--android:id="@+id/spinner"-->
<!--android:entries="@array/user"-->
<!--android:layout_width="30dp"-->
<!--android:layout_height="match_parent"></Spinner>-->
<!--</LinearLayout>-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="150dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="50dp"
android:layout_marginEnd="50dp"
android:orientation="horizontal">
<Button
android:id="@+id/wc"
android:layout_width="150dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="完成"
style="@style/buttonStyle"
android:textColor="@color/black"/>
<View
android:layout_width="50dp"
android:layout_height="match_parent"
/>
<Button
android:id="@+id/fh"
android:layout_width="150dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="返回"
style="@style/buttonStyle"
android:textColor="@color/black"/>
</LinearLayout>
</LinearLayout>
</ScrollView>

@ -188,6 +188,48 @@
android:background="@drawable/bg_santex_coppy"
android:gravity="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout7"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="花纹深度:" />
<EditText
android:id="@+id/patternDepth"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="22sp"
android:textColor="@color/black"
android:background="@drawable/bg_santex_coppy"
android:gravity="center"
android:inputType="numberDecimal"
android:imeOptions="actionDone"
android:paddingEnd="4dp" />
<!-- 单位文本:固定宽度或包裹内容 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="毫米"
android:textSize="22sp"
android:textColor="@color/black"
android:gravity="center"
android:layout_marginStart="4dp" />
</LinearLayout>
<!--<LinearLayout-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="40dp"-->

@ -93,29 +93,36 @@
android:layout_marginTop="20dp"
android:orientation="horizontal"
>
<RadioButton
android:id="@+id/test1"
style="@style/TabRadioButtonTwo"
android:textColor="@color/white"
android:drawableTop="@mipmap/test2"
android:text="安装查询"
/>
<RadioButton
android:id="@+id/xxbd"
style="@style/TabRadioButtonTwo"
android:textColor="@color/white"
android:drawableTop="@mipmap/bangding"
android:text="车牌绑定"
/>
<RadioButton
android:id="@+id/test1"
style="@style/TabRadioButtonTwo"
android:textColor="@color/white"
android:drawableTop="@mipmap/bangding"
android:text="车牌绑定"
android:visibility="invisible"
/>
<RadioButton
android:id="@+id/test2"
style="@style/TabRadioButtonTwo"
android:textColor="@color/white"
android:drawableTop="@mipmap/bangding"
android:text="车牌绑定"
android:drawableTop="@mipmap/test2"
android:text="安装查询"
android:visibility="invisible"
/>
<!-- <RadioButton-->
<!-- android:id="@+id/test3"-->
<!-- style="@style/TabRadioButtonTwo"-->
<!-- android:textColor="@color/white"-->
<!-- android:drawableTop="@mipmap/bangding"-->
<!-- android:text="车牌绑定"-->
<!-- />-->
</RadioGroup>

@ -186,13 +186,35 @@
android:id="@+id/spinnerpattern"
android:layout_width="30dp"
android:layout_height="match_parent"></Spinner>
<!-- <TextView-->
<!-- android:id="@+id/huawen"-->
<!-- style="@style/infotext"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:background="@drawable/bg_santex_coppy"-->
<!-- />-->
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout10"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="8dp"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
style="@style/alltext"
android:layout_width="90dp"
android:layout_height="match_parent"
android:background="@color/blue2"
android:text="沟槽条数:" />
<TextView
android:id="@+id/gcts"
style="@style/infotext"
android:layout_width="200dp"
android:layout_height="match_parent"
android:background="@drawable/bg_santex_coppy"
/>
<Spinner
android:id="@+id/spinnergcts"
android:layout_width="30dp"
android:layout_height="match_parent"></Spinner>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"

@ -44,7 +44,7 @@
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="280dp"
android:layout_height="380dp"
android:layout_marginTop="80dp"
android:layout_marginStart="18dp"
android:layout_marginEnd="18dp"
@ -101,13 +101,24 @@
android:layout_marginTop="30dp"
android:layout_marginRight="20dp"
android:text="登 陆" />
<!-- 新增:记住密码复选框 -->
<CheckBox
android:id="@+id/checkbox_remember"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="15dp"
android:text="记住用户名和密码"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/login_log" />
</LinearLayout>
<TextView
android:id="@+id/version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="当前版本V1.0.0"
android:textColor="@color/blue"
android:textSize="18sp"
android:gravity="center"

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp"
android:background="#f5f5f5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="APK下载安装器"
android:textSize="28sp"
android:textStyle="bold"
android:textColor="#333"
android:layout_marginBottom="32dp"/>
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@drawable/bg_button"
android:layout_marginBottom="32dp"
android:contentDescription="Android Logo" />
<Button
android:id="@+id/download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载并安装APK"
android:textSize="18sp"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:backgroundTint="#4CAF50"
android:textColor="#FFFFFF"
android:elevation="4dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击按钮开始下载并自动安装APK文件"
android:textSize="14sp"
android:textColor="#666"
android:layout_marginTop="24dp"
android:gravity="center"/>
</LinearLayout>

@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
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:fillViewport="true"
android:background="#F0F4F8"> <!-- 浅灰色背景提升质感 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">
<!-- 顶部:搜索卡片 -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_search"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:cardCornerRadius="16dp"
app:cardElevation="4dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="公交车轮胎管理"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#202020"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="20dp"/>
<!-- 车牌号输入 -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til_plate_number"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入车牌号"
android:layout_marginBottom="16dp"
app:endIconMode="custom"
app:endIconDrawable="@mipmap/search_icon">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_plate_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapCharacters"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btn_retrieve"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="立即检索"
android:textSize="16sp"
app:cornerRadius="8dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 底部:三轴轮位图展示区 -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_visual"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:cardCornerRadius="16dp"
app:cardElevation="2dp"
app:layout_constraintTop_toBottomOf="@id/card_search"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<!-- 辅助线:垂直中心线 (分隔左右轮胎) -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_vertical_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<!-- 辅助线:水平线 1 (第1轴位置) -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_axis_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="96dp" />
<!-- 辅助线:水平线 2 (第2轴位置) -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_axis_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="241dp" />
<!-- 辅助线:水平线 3 (第3轴位置) -->
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline_axis_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="399dp" />
<!-- 车头指示 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="🚗 车头方向"
android:textColor="#999999"
android:textSize="10sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- ================= 第1轴 (前轴) ================= -->
<!-- 左侧轮胎 (1轴) -->
<include
android:id="@+id/tire_left_front"
layout="@layout/item_tire"
android:layout_width="0dp"
android:layout_height="120dp"
app:layout_constraintBottom_toBottomOf="@id/guideline_axis_1"
app:layout_constraintEnd_toStartOf="@id/guideline_vertical_center"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/guideline_axis_1" />
<!-- 右侧轮胎 (1轴) -->
<!-- ================= 第2轴 (中轴) ================= -->
<!-- 左侧轮胎 (2轴) -->
<include
android:id="@+id/tire_right_front"
layout="@layout/item_tire"
android:layout_width="0dp"
android:layout_height="120dp"
app:layout_constraintBottom_toBottomOf="@id/guideline_axis_1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@id/guideline_vertical_center"
app:layout_constraintTop_toTopOf="@id/guideline_axis_1" />
<include
android:id="@+id/tire_middle_left"
layout="@layout/item_tire"
android:layout_width="0dp"
android:layout_height="120dp"
app:layout_constraintTop_toTopOf="@id/guideline_axis_2"
app:layout_constraintBottom_toBottomOf="@id/guideline_axis_2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/guideline_vertical_center"
app:layout_constraintHorizontal_bias="0.5" />
<!-- 右侧轮胎 (2轴) -->
<include
android:id="@+id/tire_middle_right"
layout="@layout/item_tire"
android:layout_width="0dp"
android:layout_height="120dp"
app:layout_constraintTop_toTopOf="@id/guideline_axis_2"
app:layout_constraintBottom_toBottomOf="@id/guideline_axis_2"
app:layout_constraintStart_toEndOf="@id/guideline_vertical_center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5" />
<!-- ================= 第3轴 (后轴) ================= -->
<!-- 左侧轮胎 (3轴) -->
<include
android:id="@+id/tire_bottom_left"
layout="@layout/item_tire"
android:layout_width="0dp"
android:layout_height="120dp"
app:layout_constraintTop_toTopOf="@id/guideline_axis_3"
app:layout_constraintBottom_toBottomOf="@id/guideline_axis_3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/guideline_vertical_center"
app:layout_constraintHorizontal_bias="0.5" />
<!-- 右侧轮胎 (3轴) -->
<include
android:id="@+id/tire_bottom_right"
layout="@layout/item_tire"
android:layout_width="0dp"
android:layout_height="120dp"
app:layout_constraintTop_toTopOf="@id/guideline_axis_3"
app:layout_constraintBottom_toBottomOf="@id/guideline_axis_3"
app:layout_constraintStart_toEndOf="@id/guideline_vertical_center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp">
<!-- 使用 LinearLayout 包裹三个 TextView -->
<LinearLayout
android:id="@+id/ll_tire_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
app:layout_constraintWidth_min="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_tire_icon">
<!-- 品牌 -->
<TextView
android:id="@+id/tv_brand"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="品牌:"
android:textColor="#333333"
android:textSize="12sp"
android:textStyle="bold" />
<!-- 规格 -->
<TextView
android:id="@+id/tv_spec"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="规格:"
android:textColor="#333333"
android:textSize="12sp" />
<!-- 安装日期/自编号 -->
<TextView
android:id="@+id/tv_self_no"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="自编号:"
android:textColor="#333333"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_install_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="日期:"
android:textColor="#333333"
android:textSize="12sp" />
</LinearLayout>
<!-- 右侧:轮胎图标 -->
<ImageView
android:id="@+id/iv_tire_icon"
android:layout_width="0dp"
android:layout_height="80dp"
android:scaleType="centerCrop"
android:src="@drawable/tire_side_view"
app:layout_constraintStart_toEndOf="@id/ll_tire_info"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_max="60dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="60dp"
android:layout_height="60dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_tire_circl"
android:orientation="vertical"
android:gravity="center"
android:padding="4dp">
<!-- 品牌/简略信息 -->
<TextView
android:id="@+id/tvBrandShort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="--"
android:textSize="12sp"
android:textStyle="bold"
android:textColor="#333333"/>
<!-- 规格简略 -->
<TextView
android:id="@+id/tvSpecShort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="8sp"
android:textColor="#666666"/>
</LinearLayout>
</FrameLayout>

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp">
<!-- 左侧:信息展示区 (对应示意图中的红色方框) -->
<!-- 右侧:轮胎图标 -->
<ImageView
android:id="@+id/iv_tire_icon"
android:layout_width="0dp"
android:layout_height="100dp"
android:src="@drawable/tire_side_view"
app:layout_constraintStart_toEndOf="@id/tv_tire_info"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintWidth_max="80dp" />
<TextView
android:id="@+id/tv_tire_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:padding="8dp"
android:text="品牌:米其林\n规格275/70R22.5\n自编号GJ-1234\n日期2023-01-01"
android:textColor="#333333"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.478"
app:layout_constraintWidth_min="120dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

@ -1,7 +1,7 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/blue</item>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- 必须包含 external-path 指向 Download 目录 -->
<external-path name="download" path="Download/" />
<external-path name="external_files" path="."/>
</paths>
Loading…
Cancel
Save