ScrollView不会在线程中以编程方式滚动

时间:2019-12-13 15:27:33

标签: java android

所以我基本上要做的是在客户端应用程序发送命令时滚动滚动视图。方法handleScrolling()可在onCreate()中工作,但是每当我从Thread调用它时,它都不会滚动。我认为从线程调用它是问题所在。

public class TeleprompterActivity extends Activity {
    static ScrollView mScrollView;
    TextView teleprompterTextView;
    String message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_teleprompter);
        teleprompterTextView = findViewById(R.id.teleprompter_text_view);
        teleprompterTextView.setText(MainActivity.contents);
        mScrollView = findViewById(R.id.scroll);

        Thread mThread = new Thread(new ServerClass());
        mThread.start();
        handleScrolling(3, true);
        Log.e("TELE", "handleScrolling at start onCrete");
    }

    void handleScrolling(final int numLines, final boolean next) {

        mScrollView.post(new Runnable() {
            public void run() {
                int currPosition = mScrollView.getScrollY();
                int textSize = (int) teleprompterTextView.getTextSize();
                if (next) {
                    int newPos = currPosition + (textSize * numLines);
                    mScrollView.smoothScrollTo(0, newPos);
                }
                if (!next) {
                    int newPos = currPosition - (textSize * numLines);
                    if (newPos < 0) {
                        newPos = 0;
                    }
                    mScrollView.scrollTo(0, newPos);
                }
            }
        });
    }

    void handleMessage(String message) {

        if (message.contains("NEXT:")) {
            try {
                int numLine = Integer.parseInt(message.substring(5));
                handleScrolling(numLine, true);
                return;
            } catch (NumberFormatException nFE) {
                nFE.printStackTrace();
                Toast.makeText(TeleprompterActivity.this, "Number Format Exception", Toast.LENGTH_SHORT).show();
            }
        }
        if (message.contains("BACK:")) {
            try {
                int numLine = Integer.parseInt(message.substring(5));
                handleScrolling(numLine, false);
            } catch (NumberFormatException nFE) {
                nFE.printStackTrace();
                Toast.makeText(TeleprompterActivity.this, "Number Format Exception", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public class ServerClass implements Runnable {
        ServerSocket serverSocket;
        Socket socket;
        DataInputStream dataInputStream;
        String receivedData;
        Handler handler = new Handler();

        @Override
        public void run() {
            try {
                serverSocket = new ServerSocket(8080);
                Log.e("TELE", "WAITIN FOR CLIENT");
                while (true) {
                    socket = serverSocket.accept();
                    dataInputStream = new DataInputStream(socket.getInputStream());
                    receivedData = dataInputStream.readUTF();
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            message = receivedData;
                            handleMessage(message);
                        }
                    });
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}

handleScrolling()方法在Thread外部调用时可以完美地工作。是参考问题还是类似的问题。 谢谢。

1 个答案:

答案 0 :(得分:0)

永远不要直接从线程更新UI组件,请调用Activity的runOnUiThread,以便您可以使用如下代码结构:

public class TeleprompterActivity extends Activity {
static ScrollView mScrollView;
TextView teleprompterTextView;
String message;
Activity thisActivity;//<--- used for saving reference to this Activity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_teleprompter);
    teleprompterTextView = findViewById(R.id.teleprompter_text_view);
    teleprompterTextView.setText(MainActivity.contents);
    mScrollView = findViewById(R.id.scroll);

    thisActivity = this;//<---- saving a reference to this activity

    Thread mThread = new Thread(new ServerClass());
    mThread.start();
    handleScrolling(3, true);
    Log.e("TELE", "handleScrolling at start onCrete");
}

void handleScrolling(final int numLines, final boolean next) {

    thisActivity.runOnUiThread(new Runnable()//<--used thisActivity.runOnUiThread here 
    {
        public void run() {
            int currPosition = mScrollView.getScrollY();
            int textSize = (int) teleprompterTextView.getTextSize();
            if (next) {
                int newPos = currPosition + (textSize * numLines);
                mScrollView.smoothScrollTo(0, newPos);
            }
            if (!next) {
                int newPos = currPosition - (textSize * numLines);
                if (newPos < 0) {
                    newPos = 0;
                }
                mScrollView.scrollTo(0, newPos);
            }
        }
    });
}