调用TextView.setText后组件发生抖动问题及解决

本文探讨了一个在Android应用中遇到的组件绘制问题,即在使用自定义Gallery滚动图片时,TextView的文本更新导致滚动效果异常抖动。通过分析原因,作者最终采用固定TextView长度的方法解决了问题,并讨论了适配性问题。文章提供了从根源解决问题的思路和实践,对于开发者处理类似动画和UI同步问题具有参考价值。
部署运行你感兴趣的模型镜像

     项目需要做一个首页新闻图片自动无限循环的组件,上面配有标识的RadioGroup。这个简单。可是后来UI设计出来的效果,要求在图片的下方添加一个灰色颜色带,再在这个颜色带上显示关于图片的标题。我想,这个也简单,分分钟的事。起先,我将表示TextView的组件引用传递个自定义的Gallery,让Gallery自动滚动时也顺带把TextView的值改变过来。可是运行起来后,发现字是改变过来了。不过Gallery的滚动效果变得有问题了,会抖动。我以为是线程影响的问题,用了handler,不行,又用线程加了延时,还是不行。无奈,在尝试了2个小时无果后,只能求助google了。最后发现一篇文章,讲的是一个播放音乐进度条反馈进度,同样调用TextView.setText方法,发生了进度条向右抖动的情况。解决方案是将TextView的长度写死,不要用wrap_content,于是,我的问题也这么解决了。但是将长度写死又带来了适配的问题。当然这又是另外一个问题了。

    总结:一、这个问题应该是android中组件绘制过程带来的影响。

              二、多上google,少用百度

您可能感兴趣的与本文相关的镜像

AutoGPT

AutoGPT

AI应用

AutoGPT于2023年3月30日由游戏公司Significant Gravitas Ltd.的创始人Toran Bruce Richards发布,AutoGPT是一个AI agent(智能体),也是开源的应用程序,结合了GPT-4和GPT-3.5技术,给定自然语言的目标,它将尝试通过将其分解成子任务,并在自动循环中使用互联网和其他工具来实现这一目标

package com.example.test; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import android_serialport_api.SerialPort; import android_serialport_api.SerialPortFinder; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class MainActivity extends AppCompatActivity { private TextView serialNameTextView; private TextView forkStatusTextView; private Button openSerialButton; private SerialPort serialPort; private InputStream inputStream; private OutputStream outputStream; private ReadThread readThread; private static final String TAG = "SerialForkDetection"; private static final String DEFAULT_SERIAL_PORT = "/dev/ttyS1"; // 默认串口设备 private static final int BAUD_RATE = 9600; // 波特率 // 叉簧状态定义 private static final int FORK_STATUS_ON_HOOK = 0; // 挂机状态 private static final int FORK_STATUS_OFF_HOOK = 1; // 摘机状态 private static final int FORK_STATUS_UNKNOWN = 2; // 未知状态 private boolean isSerialOpen = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); serialNameTextView = findViewById(R.id.SerialName); forkStatusTextView = findViewById(R.id.ForkSpringsStatus); openSerialButton = findViewById(R.id.OpenSerial); openSerialButton.setOnClickListener(v -> toggleSerialPort()); } private void toggleSerialPort() { if (isSerialOpen) { // 关闭串口 try { if (serialPort != null) { serialPort.close(); serialPort = null; } if (readThread != null) { readThread.interrupt(); readThread = null; } inputStream = null; outputStream = null; isSerialOpen = false; openSerialButton.setText("打开串口"); serialNameTextView.setText("未连接"); forkStatusTextView.setText("未知状态"); Toast.makeText(this, "串口已关闭", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "关闭串口失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } else { // 打开串口 try { SerialPortFinder serialPortFinder = new SerialPortFinder(); String[] devices = serialPortFinder.getAllDevicesPath(); if (devices == null || devices.length == 0) { Toast.makeText(this, "没有找到可用的串口设备", Toast.LENGTH_SHORT).show(); return; } String devicePath = devices.length > 0 ? devices[0] : DEFAULT_SERIAL_PORT; serialPort = new SerialPort(devicePath, BAUD_RATE); inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); serialNameTextView.setText(devicePath.substring(devicePath.lastIndexOf('/') + 1)); readThread = new ReadThread(); readThread.start(); isSerialOpen = true; openSerialButton.setText("关闭串口"); Toast.makeText(this, "串口已打开", Toast.LENGTH_SHORT).show(); } catch (UnsatisfiedLinkError e) { e.printStackTrace(); Toast.makeText(this, "native库加载失败,请检查so文件", Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "发生未知错误: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } } private class ReadThread extends Thread { @Override public void run() { super.run(); while (!isInterrupted()) { try { if (inputStream == null) return; byte[] buffer = new byte[1024]; int size = inputStream.read(buffer); if (size > 0) { // 解析叉簧状态 int forkStatus = parseForkStatus(buffer, size); // 更新UI Message message = handler.obtainMessage(); message.arg1 = forkStatus; handler.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); return; } } } private int parseForkStatus(byte[] data, int size) { // 这里根据实际设备协议解析叉簧状态 // 假设收到0x01表示摘机,0x00表示挂机 if (size > 0) { if (data[0] == 0x01) { return FORK_STATUS_OFF_HOOK; } else if (data[0] == 0x00) { return FORK_STATUS_ON_HOOK; } } return FORK_STATUS_UNKNOWN; } } private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.arg1) { case FORK_STATUS_ON_HOOK: forkStatusTextView.setText("挂机状态"); break; case FORK_STATUS_OFF_HOOK: forkStatusTextView.setText("摘机状态"); break; case FORK_STATUS_UNKNOWN: forkStatusTextView.setText("未知状态"); break; } return true; } }); @Override protected void onDestroy() { super.onDestroy(); // 关闭串口 if (serialPort != null) { serialPort.close(); serialPort = null; } // 停止读取线程 if (readThread != null) { readThread.interrupt(); readThread = null; } } }获取叉簧状态
08-02
package com.ape.factory; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.widget.TextView; import com.ape.factory.base.ItemTestBaseActivity; import com.ape.factory.mmi.MmiUtils; import com.tn.CQAtest.CQAConstant; import com.tn.CQAtest.SENSORTEST; import com.tn.tno.LogUtil; import java.io.FileNotFoundException; import java.io.FileReader; public class HALL extends ItemTestBaseActivity{ private TextView text1, text2; Runnable mRunnable; private int num = 1; private int mFTM_rsp_key=0; private boolean mCQACommandTest=false; private int firstHallResult = 1; private boolean firstData = true; private boolean testResult = false; private final String DevicePath = "/sys/bus/platform/drivers/hall/hall_state"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); Bundle bundle = intent.getExtras(); setContentView_ftm(R.layout.hall); setBtnPassEnabled(false); text1 = (TextView) findViewById(R.id.text1); text2 = (TextView) findViewById(R.id.text2); if (bundle != null) { mFTM_rsp_key = bundle.getInt(MmiUtils.MMI_RSP_KEY); mCQACommandTest = bundle.getBoolean(CQAConstant.CQA_COMMAND_KEY,false); LogUtil.i( "mFTM_rsp_key :"+mFTM_rsp_key); LogUtil.i( "mCQACommandTest :"+mCQACommandTest); } initSensor(); } private void initSensor(){ firstData = true; hallHandler.sendEmptyMessageDelayed(MSG_GET_DATA,100); } private void displayHallStatus() { char[] buffer = new char[4]; int mHALLState = 1; try { FileReader file = new FileReader(DevicePath); int len = file.read(buffer, 0, 4); mHALLState = Integer.valueOf((new String(buffer, 0, len)).trim()); file.close(); if (firstData){ firstHallResult = mHALLState; firstData = false; } LogUtil.i("readhallstatus mHALLState=" + mHALLState); text1.setText("HALL:" + mHALLState + " (0:COVER; 1:OPEN)"); text2.setVisibility(View.VISIBLE); text2.setText("HALL: " + mHALLState); if (mHALLState != firstHallResult) { mBtnPass.setEnabled(true); if(mCQACommandTest){ SENSORTEST.SENSOR_HALL_TEST_DONE(); mBtnPass.performClick(); } } if (mIsFullTest == 1 && mHALLState != firstHallResult) { mBtnPass.performClick(); } } catch (FileNotFoundException e) { LogUtil.e( "This kernel does not have HALL support "+e.getMessage()); text1.setText("This kernel does not have HALL support"); text2.setVisibility(View.INVISIBLE); } catch (Exception e) { LogUtil.e( ""); } hallHandler.sendEmptyMessageDelayed(MSG_GET_DATA,500); } private final int MSG_GET_DATA = 0x01B; private Handler hallHandler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case MSG_GET_DATA: displayHallStatus(); break; default: break; } } }; @Override public void onDestroy() { if (hallHandler != null){ hallHandler.removeCallbacksAndMessages(null); hallHandler = null; } super.onDestroy(); } }
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值