小编Tre*_*vor的帖子

在画布上绘制透明形状

我有一个占据整个屏幕的背景图像.我在背景上绘制画布并将其颜色设置为白色,因此您无法看到图像.我想要实现的是然后在白色画布上绘制一个透明的形状,并通过该形状的位置显示背景图像.我正在使用surfaceView并实现SurfaceView.Callback.

android canvas transparent

8
推荐指数
2
解决办法
1万
查看次数

渐变在SurfaceView中显示为带状,但在普通视图中看起来非常平滑

我的问题是,在a中绘制一个简单的测试图像(带有渐变填充的矩形)时SurfaceView,渐变具有颜色条带.当在简单的扩展中绘制具有相同渐变的完全相同的矩形时View,渐变看起来非常平滑,并且与我期望的32位颜色一样好.

这是在相同的布局内使用与测试SurfaceView一起放置的测试并排发生的.ViewActivity

有关信息,在Activity课程中我window.setFormat(PixelFormat.RGBA_8888)打算将Activity切换为32位颜色,因为这是过去消除渐变中的条带的解决方案(但是,我相信在某个Android级别不再需要这个) 32位是默认值).我minSdkVersion8岁.

出现在onDraw()简单扩展View和以下的测试代码SurfaceView是:

    Paint paint = new Paint();
    paint.setStyle(Paint.Style.FILL);
    paint.setAntiAlias(false);
    paint.setFilterBitmap(false);
    paint.setDither(false); 
    Shader shader = new LinearGradient(
            0,
            0,
            0,
            200,
            new int[]{0xff150d2f,0xff432b96},
            null,
            Shader.TileMode.CLAMP
            );

    paint.setShader(shader);    
    canvas.drawRect(0,0,getWidth(),getHeight(), paint);
Run Code Online (Sandbox Code Playgroud)

以下是显示SurfaceView上述和正常情况View下的屏幕截图.我意识到这个例子中的条带非常微妙; 当渐变扫过较小的颜色带时,它会更加明显.

截图

有什么建议吗?

崔佛

android surfaceview

7
推荐指数
1
解决办法
2811
查看次数

在XML中引用自定义Shape类

我一直在扩展标准范围Shape(类别RectShape,OvalShape通过扩展等)Shape类来创建自己的自定义设置的形状.例如,我创建了一个简单的TriangleShape类,如下所示:

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.shapes.Shape;

public class TriangleLeftShape extends Shape {

@Override
public void draw(Canvas canvas, Paint paint) {
    Path path = new Path();
    path.setLastPoint(0, getHeight()/2);
    path.lineTo(getWidth(), getHeight());
    path.lineTo(getWidth(), 0);
    path.close();
    canvas.drawPath(path, paint);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要做的是Drawable使用这个类完全用XML 创建资源.这可能吗?

我知道使用其中一个标准形状只需通过以下示例实现,其中<shape>元素表示ShapeDrawable:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<gradient android:startColor="#FFFF0000" android:endColor="#80FF00FF"
        android:angle="270"/>
</shape>
Run Code Online (Sandbox Code Playgroud)

我无法看到的是,如何在XML中传递一个自定义Shape类,这个类ShapeDrawable是用XML定义的.我知道该android:shape属性只是传递一个枚举值,它只能是矩形,椭圆形,直线或环形.似乎没有XML属性来指定自定义Shape类.

但是, …

android drawable

7
推荐指数
1
解决办法
1298
查看次数

SVG转换 - 存储Path,Paint和Matrix对象的有效方法?

在我的Android应用程序中,我创建了一个SVG图像转换器类.它解析SVG XML数据并将其转换为适当的Path,Paint和Matrix对象,然后将其应用于Canvas.然后使用这个类我实现了一个View,它使用我的SVG转换器类在屏幕上绘制我在Inkscape中生成的图像.到现在为止还挺好.(我很欣赏编写我自己的SVG转换器可以考虑重新发明,考虑到它之前已经完成,但对我来说,这是我第一个Android应用程序中的一个有用的学习练习,并希望能给我一些额外的灵活性.)

使用SVG的目的是让我可以快速轻松地编写各种图形仪表设计.每个仪表通常由一段图形组成,只需要绘制一次(例如仪表面和图例),以及定期更新的图形(指针角度,数值文本).

目前我的仪表View效率不高,因为每次调用onDraw()时,都会调用我的SVG类来调整整个SVG文件,以生成Canvas的所有矢量数据.

我想要做的是对矢量数据进行一些中间存储,这样SVG XML文件只需要解析一次.因此,我认为View可以在第一个onDraw()上从SVG文件中进行惰性初始化,然后将所有生成的Paths,Paint和Matrix对象存储到各种列表中.然后,在每个后续的onDraw()上,我只是将它们从List中拉出来,并通过那些进入Canvas.

这样做的另一个优点是使用单独的列表来存储"移动"的矢量图形部分,例如仪表指针.我想通过为Inkscape中代表指针的路径组分配一个"魔术"ID来做到这一点; 然后,SVG解析器类将识别出该单独的组需要单独存储到"静止"图形中.然后,每当我需要根据测量数据刷新指针的角度时,View将仅将旋转变换应用于该束矢量数据.事实上,我正在考虑这样做,以便移动指针图形实际上是在子视图中绘制的,这样只有在必须刷新指针时才重绘子视图.

所有这一切的最终目标是:我(或者甚至用户)可以启动像Inkscape这样的矢量成像程序,并快速生成仪表小部件的新设计.我嵌入了一些元数据来指示必须根据测量数据操作哪些图形位.

我不是要求解决问题,而是希望听到关于我在这里做什么的意见,以及我提出的建议是否可以以更加优化的方式完成.缓存Path和Paint对象组是否内存效率非常低?

此外,一旦它足够好(!)我很乐意在某个地方发布我的SVG类,如果有人发现它有用的话.

svg android

6
推荐指数
1
解决办法
1629
查看次数

Canvas restore() 在极少数情况下导致下溢异常

通过 ACRA,我收到了少量来自软件 alpha 版本的报告,这些报告显示在对Canvas.restore(). 例外是java.lang.IllegalStateException: Underflow in restore

我很清楚,如果restore()调用次数多于save()调用次数,则会发生此异常。但是,通过非常仔细的代码检查,我绝对确定所有对canvas.save()和 的调用canvas.restore()都是平衡的。也就是说,所有对 的调用canvas.save()肯定会在稍后阶段通过对 的调用进行平衡canvas.restore()。我还可以确认没有条件、异常或方法的早期返回可能导致丢失canvas.save()导致堆栈下溢。

此外,这个问题似乎是一种罕见的边缘情况,它导致异常在每秒渲染多次的图形代码中只发生几次。

发生这种情况的代码结构是:

protected void onDraw(Canvas canvas) {
    ...
    someMethod(canvas);
    ...
}

void someMethod(Canvas canvas)
{
    ....
    canvas.save();
    ....
    someOtherMethod(Canvas canvas);
    ....
    canvas.restore();  
    ....
}

void someOtherMethod(Canvas canvas)
{

    ....
    canvas.save();
    ....
    for ( ... ) {

        ....
        canvas.save();
        ...
        canvas.restore();
        ...
    }
    ....
    canvas.restore();   // *** exception here ***   
    .... …
Run Code Online (Sandbox Code Playgroud)

android underflow android-canvas

6
推荐指数
1
解决办法
4426
查看次数

以编程方式删除ViewPager,何时(或我如何确保)包含的碎片被销毁?

事先搜索过这个问题,我可以找到很多关于Fragment从a中动态添加和删除所选s的讨论ViewPager.然而,我真正关心的是如何以编程方式ViewPager从包含中删除整个'干净利落' ViewGroup,当ViewPager用于Fragment通过a 显示s时FragmentPagerAdapter,确保包含的Fragments被正确销毁.

为了进一步扩展这个问题,我有一个横向双窗格布局,其中从Fragment左侧的列表中进行选择,然后选择的内容放在a的右侧FrameLayout.关键是内容可能会或可能不会被分页.因此,内容必须以ViewPager格式显示,或者如果没有分页,则应Fragment直接用单个表示.

为了显示单个Fragment,我只需FragmentTransaction像往常一样执行以便将其Fragment放入FrameLayout容器中.另一方面,如果要显示的是分页内容,那么我创建一个ViewPager并将其添加为FrameLayout.

当我需要更改内容时,如果以前的内容是独立的,Fragment那么我可以直接删除它FragmentTransaction .remove().当我这样做时,按预期Fragment进行onPause()... onDestroy()循环.如果之前的内容是a,ViewPager那么我将其从FrameLayout使用中删除.removeAllViews().在这里,我来了问题:我看不到任何的onPause()... onDestroy()方法被称为在任何的Fragment举行之内,且s ViewPager通过FragmentPagerAdapter.

从用户的角度来看,应用程序运行正常.经过几轮ViewPager被移除后,我可以看到GC回收内存.但是,我不喜欢这样一个事实:那些Fragment生命方式的终结方法没有被调用,因为我不能在它们内部做任何清理,而且它似乎并不"正确".

有没有我可以以勾去掉进入一个方法ViewPagerFragment当S ViewPager从其母体分离,也许?换句话说,当我知道 …

android android-fragments android-viewpager

5
推荐指数
1
解决办法
4907
查看次数

在退出之前的混乱集成后,无法从主分支完全集成到功能分支

我正在使用Perforce P4V客户端(版本2013.1/611291,日期为2013年3月20日).

我试图从主分支合并/集成到我的功能分支.自从我这么做以来已经很长时间了,因此大量的文件被添加到更改列表中.然后我解决了无法自动合并的冲突文件.然后我提交了变更清单.在这之后,我发现一些文件仍处于混乱的冲突状态.究竟为什么对我来说是一个谜,但我没有尝试修复它们,我认为完全撤消Merge/Integrate并重新开始会更容易.

要撤消合并/集成,我使用了"退出"选项.所有受影响的文件都被添加到"退出"更改列表中,然后我提交了它.我的功能分支现在又回到了它的开始状态,除了显然现在所有受影响的文件都将其修订版号增加了两倍,受影响文件的历史记录显示了集成,然后是后续"退出".

问题是如果我再次尝试Merge/Integrate选项,那么Perforce想要放入集成更改列表的文件数量现在只是它最初尝试集成的一小部分.换句话说,它并没有添加大量的文件,我知道这些文件在主分支的开发方面肯定是进一步向前发展的.

我似乎能够解决这个问题的唯一方法是使用高级选项Force integration on all revisions, disregarding revision history (-f).设置此选项后,它将添加以合并分支中的所有文件.

我怀疑问题与文件现在在其历史记录中标记了集成这一事实有关,因此Perforce使用该点作为基础.混乱的整合被"退出"的事实对此没有任何影响.

我也试图做回滚,但同样的问题仍然存在.

我怎么解决这个问题?

编辑 我后来意识到存在以下类似问题: 如何在Perforce中撤消集成,并且仍然能够重做它?

perforce

5
推荐指数
1
解决办法
2409
查看次数

我可以以某种方式包含和使用给定.jar库的多个版本吗?

我很欣赏这听起来很荒谬,但是有可能将.jar库的两个不同版本放到一个Android项目中(两个版本显然都有相同或重叠的包和类名),并且在某种程度上明确地指向其中一个将库的类导入到我自己的Java源代码中?

我的开发环境是带有Gradle的Android Studio.

我考虑这样做的原因(如果可能的话)是因为我依赖一个闭源供应商提供的.jar驱动程序库,用于我的Android应用程序使用的USB设备.该厂商在其最新的驱动程序中增加了对更新芯片版本的支持,但与此同时,他们已经放弃了对旧版芯片的支持.这是他们为自己的理由做出的决定,不太可能被逆转.我的想法是以某种方式在我的应用程序中携带新旧版本的库,以便我可以继续支持旧硬件.

我想这样的事情在理论上是可行的,但是一个复杂的事情,可能需要一个.jar被反编译并且包名称改变了?

java android

5
推荐指数
1
解决办法
668
查看次数

覆盖RelativeLayout的onMeasure()以约束其纵横比

我有一个扩展的RelativeLayout,当使用编程定位和大小时RelativeLayout.LayoutParams,需要将自己限制在给定的宽高比.通常,我希望它将自己约束为1:1,因此如果RelativeLayout.LayoutParams包含width200和height100的100,则自定义RelativeLayout将自身约束为100 x 100.

为了达到类似的目的,我已经习惯于覆盖onMeasure()普通的自定义View.例如,我创建了自己的SVG图像转换器,并且View渲染SVG图像的自定义具有重写onMeasure(),以确保调用setMeasuredDimension()包含(a)符合原始测量规范的尺寸,以及(b)匹配宽高比原始SVG图像.

回到我的习惯RelativeLayout,我希望以类似的方式约束自己,我试过压倒onMeasure()但我没有取得多大成功.知道RelativeLayout我的onMeasure()所有子项View放置,我目前通常尝试做的,但没有预期的结果,是覆盖onMeasure(),以便我最初修改维度规范(即应用我想要的约束)然后打电话super.onMeasure().像这样:

@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);      
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    // Restrict the aspect ratio to 1:1, fitting within original specified dimensions
    int chosenDimension = …
Run Code Online (Sandbox Code Playgroud)

android relativelayout

4
推荐指数
1
解决办法
5266
查看次数

Activity 类只能在开发/调试期间启动吗?

我面临的一个常见情况是,我希望View在将自定义项目作为大型应用程序的一部分进行开发时,在屏幕上以可见方式对其进行测试。我意识到单元测试的存在,特别是使用ActivityUnitTestCase,但据我了解,这些框架实际上并没有在屏幕上可见地附加组件。

目前,我倾向于这样做的方法是将组件放置在应用程序中实际使用的任何位置。这通常意味着需要等待一段时间应用程序启动或在应用程序可见之前浏览应用程序的某些部分,这可能会变得很麻烦。

我发现的更好的方法是在应用程序中创建一个Activity纯粹出于测试目的而存在的应用程序(例如,仅显示我正在开发的自定义View),启动该应用程序以显示我正在处理的自定义View(或其他内容)。为此,我Activity在清单中分配给该过滤器的唯一意图过滤器是android.intent.action.MAIN,而不是 android.intent.category.LAUNCHER。然后,我可以简单地在 Android Studio 中创建一个运行/调试配置来Activity直接启动它。据我认为,这实际上允许我拥有Activity只能由我从 IDE 启动的类。

我的问题是:

  1. 省略是否可以android.intent.category.LAUNCHER保证应用程序的用户无法Activity以任何方式启动该应用程序,也无法意识到它的存在?这是一个安全的地方吗Activity只开设用于发展的课程

  2. 是否有任何类型的工作流程或测试框架可以用来改进我的做法?

android android-view android-activity android-testing

3
推荐指数
1
解决办法
613
查看次数

在onDraw()方法中,为什么提供的Canvas已经具有比例?

在当前的测试项目中,我有一个自定义视图,我将其命名为SVGView,它只是将一些矢量图形(路径等)绘制到Canvas中.

XML布局文件只包含一个FrameLayout,它包含一个子SVGView.当前示例中SVGView 的android:layout_widthandroid:layout_height属性都设置为300px(包含FrameLayout的空间足够容纳).在SVGView中onMeasure(),调用setMeasuredDimension()给出参数300,300 .

onDraw()调用方法将图形绘制到Canvas对象时,我发现Canvas没有标识矩阵; 相反,Canvas已经应用了一些规模转换.这是什么原因?我(错误地)假设Canvas的缩放比例为1,因为View的实际尺寸,Canvas以及它在屏幕上的表示都匹配.

我问这与我在前面的问题中详细描述的问题有关:Canvas绘图缓存位图有点模糊或具有反别名.我发现当我将缓存位图绘制回Canvas时,它与原始矢量图形相比有点模糊,尽管事实上我正在使用没有重新缩放并使用关闭消除锯齿的Paint来绘制位图.我现在只是绝对相信必须有一些缩放过程,我不知道这会导致这种情况发生在位图上.要发现onDraw()的Canvas参数已经应用了一些缩放转换可能是解决这个问题的一个重要线索 - 但我无法理解为什么它有这样的缩放,当Canvas的尺寸肯定与该区域完全匹配时它最终画的屏幕.

谢谢,

崔佛

android

2
推荐指数
1
解决办法
1352
查看次数

使用ActionBarSherlock; 遇到2.2和ICS/JB之间的View.getLocationOnScreen()不一致

RelativeLayout的大小占据了包含的所有屏幕区域Activity.也就是说,它会填充除通知栏以外的所有屏幕区域.

我正在使用ActionBarSherlock.ActionBar设置为覆盖模式使用getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY).因此,我的RelativeLayout跨度从通知栏的正下方直到屏幕的底部,以及View它所拥有的任何子项都可能放在ActionBar后面.因此ActionBar肯定在叠加模式下运行.我确认在运行2.2,4.0.x(ICS)和4.1(JB)的设备上就是这种情况.

因为我的应用程序在其中实现了拖放机制RelativeLayout,我需要知道布局在屏幕上的位置,以便我可以更正返回的绝对屏幕Y触摸值getRawY().为了实现这一目标,布局阶段已经完成之后,我一直在呼吁mRelativeLayout.getLocationOnScreen()的内部onWindowFocusChanged().

在我的4.0和4.1设备上,调用getLocationOnScreen()产生的Y值与最顶部通知栏的高度(以像素为单位)相匹配.为了确定通知栏和ActionBar组合的高度,我将返回的Y值添加getLocationOnScreen()到ActionBarSherlock getHeight()方法的结果中.

问题是,在2.2设备上进行测试时,getLocationOnScreen()返回的Y值已经是通知栏高度加上ABS高度.即使ABS设置为叠加模式,也是如此.

有关SO的一些问题涉及令人难以置信的结果getLocationOnScreen(); 一个在这里有一个答案,给了我的想法,只是放弃getLocationOnScreen(),而是计算RelativeLayout顶级Ÿ通过从总屏幕高度减去布局的高度偏移:

DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int mRelativeLayoutYOffs = dm.heightPixels - mRelativeLayout.getMeasuredHeight(); 
Run Code Online (Sandbox Code Playgroud)

我发现这个结果的奇怪之处在于它似乎给了我与我相同的不一致性getLocationOnScreen().在2.2上发生的事情是,.getMeasuredHeight()RelativeLayout实际的调用实际上似乎是给出一个高度值,其ActionBar高度从实际高度中减去RelativeLayout,即使 ABS设置为叠加并且我已经在视觉上确认它肯定在叠加模式.

我现在能想到的最好的策略是getLocationOnScreen()根据操作系统版本来区分不同的结果 .如果它是2.2,那么我知道它包括ABS高度.如果4.0以上,则不会.2.2和4.0之间的任何东西,我还不确定.也许人们可以帮助填补这些细节.也许差异是在本机支持ActionBar的操作系统版本中引入的?如果它是可预测的并且很好地定义了行为是什么,那么希望这将是一个安全的策略.

如果不这样做,是否有任何关于确定RelativeLayout顶部和左侧屏幕位置的方法的建议,以便纠正绝对屏幕触摸值?

android actionbarsherlock

2
推荐指数
1
解决办法
2563
查看次数