Android View如何边绘制边左移动?

eddysong9280 2019-07-31 03:07:24
在手机屏幕最右侧不停的画一条竖线,推动前面已经画好的竖线向左移动。
效果如同在手机屏幕最右侧不停的出现一条条竖线,推着前面已经画好的竖线 一点点左移,最终铺满手机屏幕。

怎么推动前面画好的竖线一条条左移动呢?
...全文
366 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
assky124 2019-08-06
  • 打赏
  • 举报
回复
你可以试试把绘图区域切割一下,固定的区域,用Image缓存。
eddysong9280 2019-08-06
  • 打赏
  • 举报
回复
可以在公司或者学习群里问高手。肯定有解答办法。
若有办法 记得在此贴子里分享嗯,感谢。
eddysong9280 2019-08-05
  • 打赏
  • 举报
回复
收到了 谢谢谢谢。
m-oj 应用层 2019-08-05
  • 打赏
  • 举报
回复
引用 14 楼 eddysong9280 的回复:
[quote=引用 12 楼 m-oj 的回复:] 试了下,没有你说的情况
怎么实现的???求教。[/quote] import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; import java.util.Random; /** * @author : moj * @date : 2019/8/2 * @description : */ public class LineView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mSurfaceHolder; private int mWidth; private int mHeight; private int size; private Paint mPaint; private Queue<Integer> mQueue = new LinkedList<>(); private Random mRandom = new Random(); private int mLineWidth; private int mGap; private int marginL; private int marginR; public LineView(Context context) { this(context, null); } public LineView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LineView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mSurfaceHolder = getHolder(); mSurfaceHolder.addCallback(this); mPaint = new Paint(); mPaint.setColor(Color.GREEN); } private void drawLine(){ if(mQueue.size() == size){ mQueue.poll(); } int he = mRandom.nextInt(ScreenUtil.px2dip(getContext(),mHeight)) / ScreenUtil.px2sp(getContext(), mLineWidth); // Log.i("fff", he+""); mQueue.add(he); Canvas canvas = mSurfaceHolder.lockCanvas(); if(canvas == null){ return; } canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); Iterator<Integer> integerIterator = mQueue.iterator(); int count = Math.max(mQueue.size()-1,0); while (integerIterator.hasNext()){ int h = integerIterator.next(); int x = mWidth - mLineWidth*(count+1) - count * mGap + mLineWidth/2; for (int i = 0; i <h; i++) { mPaint.setColor(randomColor()); canvas.drawPoint(x, mHeight - i * mLineWidth, mPaint); } count --; } mSurfaceHolder.unlockCanvasAndPost(canvas); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); // Log.i("fff",mWidth+","+ScreenUtil.getScreenWidth(getContext()) + ", "+getRight()); for (int i = ScreenUtil.dip2px(getContext(), 2);;i++){ if(mWidth % i == 0 && (mWidth / i) % 2 != 0){ mLineWidth = mGap = i; size = mWidth / mGap; mPaint.setStrokeWidth(mLineWidth); break; } } if(getLayoutParams() instanceof ViewGroup.MarginLayoutParams){ marginL = ((ViewGroup.MarginLayoutParams) getLayoutParams()).leftMargin; marginR = ((ViewGroup.MarginLayoutParams) getLayoutParams()).rightMargin; } } @Override public void surfaceCreated(SurfaceHolder holder) { new Thread(new Runnable() { @Override public void run() { while (true){ // long i = System.currentTimeMillis(); drawLine(); // Log.i("fff", (System.currentTimeMillis() - i) +""); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } public static int randomColor() { Random random = new Random(); int r = random.nextInt(256); int g = random.nextInt(256); int b = random.nextInt(256); return Color.argb(255,r,g,b); } } 这是我的代码,可以参考一下
eddysong9280 2019-08-05
  • 打赏
  • 举报
回复
引用 12 楼 m-oj 的回复:

试了下,没有你说的情况


怎么实现的???求教。
ink_s 2019-08-05
  • 打赏
  • 举报
回复
好像无解?
除非不用Invalidate() ?
不知道有什么办法新加一条线的时候而不重绘以前的线条。

eddysong9280 2019-08-05
  • 打赏
  • 举报
回复
translate可以实现画布平移,省去了重新描画已经画好的点的时间。
咱们现在的方法是定时描画所有的点,2000*1000 点太多 效率低。
m-oj 应用层 2019-08-05
  • 打赏
  • 举报
回复
引用 20 楼 eddysong9280 的回复:
感觉还得结合translate实现
现在是画点太多的问题,你用translate还不是一样要画这么多点?
eddysong9280 2019-08-05
  • 打赏
  • 举报
回复
感觉还得结合translate实现
eddysong9280 2019-08-05
  • 打赏
  • 举报
回复
不是渐变。
是颜色不同的各个点,颜色随机 没有规律。
不知怎么实现了........
m-oj 应用层 2019-08-05
  • 打赏
  • 举报
回复
引用 17 楼 eddysong9280 的回复:
[quote=引用 14 楼 eddysong9280 的回复:] [quote=引用 12 楼 m-oj 的回复:] 试了下,没有你说的情况
怎么实现的???求教。[/quote] 当每个竖线有2000个点组成且每条竖线占据1像素的宽度, 当满屏幕时, 你可以试一下描画的效率。[/quote] 画点肯定效率低,如果你的颜色渐变的画,建议改用drawable来画
eddysong9280 2019-08-05
  • 打赏
  • 举报
回复
引用 14 楼 eddysong9280 的回复:
[quote=引用 12 楼 m-oj 的回复:]

试了下,没有你说的情况


怎么实现的???求教。[/quote]


当每个竖线有2000个点组成且每条竖线占据1像素的宽度, 当满屏幕时, 你可以试一下描画的效率。
eddysong9280 2019-08-02
  • 打赏
  • 举报
回复
其实那是一些点。一竖条占据一像素,一竖条大约有几百个点组成,每个点的颜色不一样。
为描述问题方便,我使用线来描述了。但是问题一样。
头发还没秃a 2019-08-02
  • 打赏
  • 举报
回复
Scrolls可以达到效果吧
m-oj 应用层 2019-08-02
  • 打赏
  • 举报
回复
试了下,没有你说的情况
eddysong9280 2019-08-01
  • 打赏
  • 举报
回复
上面我写的代码可以实现左移,但是最新的竖线不是在屏幕最右侧了,translate后,pointX= 1080画的点不在屏幕最右侧,而是左移了(坐标1080左移了)。
pointX++ 也不好使。
eddysong9280 2019-08-01
  • 打赏
  • 举报
回复
重绘效率低,
每条线有几百个点组成的,快铺满屏幕时,1800(一条线占据一像素)*500这么些点,重绘一下耗时。。。。。
m-oj 应用层 2019-08-01
  • 打赏
  • 举报
回复
引用 6 楼 eddysong9280 的回复:
整体效果是当来一条新竖线时 画在屏幕最右侧,同时前面所有已经画好的竖线 挨个左移一像素。 看着是屏幕最右侧出现最新的竖线(竖线宽度是1像素),推着前面的竖线一点点左移。右边不停的进线,屏幕左侧不停的出。 现在是在定时器里走如下程序:pointX=屏幕宽度(假设=1080),这样drawPoint始终画在屏幕最右侧。画完画布左移一像素。当有新数据时,pointX= 1080,但是canvas已经左移了,导致再drawPoint时,所画的点没有画在屏幕最右侧。 不知这个pointX, translate 怎么结合实现最右侧进,一点点左出的效果? //画最新的1 ping for (int n = 0; n < mPingData.size(); n++) { double[] point = mPingData.get(n); SonarUtils.SonarCard card = SonarUtils.getColorIdByPointDb(point[0], point[2], point[1]); mPaint.setColor(getResources().getColor(card.getColoValuerId())); float pointY = ((float) getHeight() / (float) mPingData.size()) * (float) n; mBufferCanvas.drawPoint(pointX, pointY, mPaint); //画一像素的竖线点 } mBufferCanvas.translate(-1, 0); invalidate();
为什么要左移呢?现在这样不停重绘就已经有左移的效果了啊。
eddysong9280 2019-08-01
  • 打赏
  • 举报
回复
整体效果是当来一条新竖线时 画在屏幕最右侧,同时前面所有已经画好的竖线 挨个左移一像素。
看着是屏幕最右侧出现最新的竖线(竖线宽度是1像素),推着前面的竖线一点点左移。右边不停的进线,屏幕左侧不停的出。

现在是在定时器里走如下程序:pointX=屏幕宽度(假设=1080),这样drawPoint始终画在屏幕最右侧。画完画布左移一像素。当有新数据时,pointX= 1080,但是canvas已经左移了,导致再drawPoint时,所画的点没有画在屏幕最右侧。
不知这个pointX, translate 怎么结合实现最右侧进,一点点左出的效果?

//画最新的1 ping
for (int n = 0; n < mPingData.size(); n++) {
double[] point = mPingData.get(n);
SonarUtils.SonarCard card = SonarUtils.getColorIdByPointDb(point[0], point[2], point[1]);
mPaint.setColor(getResources().getColor(card.getColoValuerId()));
float pointY = ((float) getHeight() / (float) mPingData.size()) * (float) n;
mBufferCanvas.drawPoint(pointX, pointY, mPaint); //画一像素的竖线点
}
mBufferCanvas.translate(-1, 0);
invalidate();
m-oj 应用层 2019-08-01
  • 打赏
  • 举报
回复
引用 4 楼 eddysong9280 的回复:
[quote=引用 3 楼 m-oj 的回复:] [quote=引用 2 楼 eddysong9280 的回复:] [quote=引用 1 楼 m-oj 的回复:] 事先画好这个图,然后transaction动画从右到左移动就好了
不是。 这个是动态的,如同心电图一样。右边不停的画最新的线, 左边的线依次推着左移。[/quote] 那可以用surfaceview来绘制,先定好线条属性(长度,宽度),根据view的宽度定义数组长度,定义个刷新时间如50ms, 每50ms重新绘制一次,每次将数组里的数据绘制出来即可[/quote] 当有最新的竖线时,前面的屏幕上的竖线 怎么实现左移呢?将数组里面的数据取出 每条线左移一个像素然后描画所有的线?效率是不是太低了?[/quote] 好好利用数据结构啊,队列。。
加载更多回复(5)

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧