【问题标题】:How to create a semi-transparent instruction page in Android?如何在Android中创建一个半透明的指令页面?
【发布时间】:2015-08-13 22:09:03
【问题描述】:

我是 Android 新手,过去 2 天一直在尝试解决这个问题,但可以找到解决方案。任何帮助将不胜感激。如何在 Android Market 中创建一个半透明的指令页面供 App 卡路里计数器使用?

【问题讨论】:

  • @PedroRainho 是的,我尝试在我的应用程序Wordlist Builder 中执行其中一项操作。看看谷歌播放?如果有用,我可以和你分享代码。
  • 您好,请问您是怎么​​做到的?
  • 半透明层后面的层你能摸一下吗??
  • @user2078315 不,你必须先关闭半透明层。
  • @Shayanpourvatan 将应用程序 Wordlist Builder 的源代码推送到 Github here。如果您需要我的关注,请在 repo 上发表评论。

标签: android


【解决方案1】:

创建一个新的activity并将顶层视图设置为具有半透明背景:

android:background="#c0000000"

编辑:您还需要将活动声明为具有透明背景。为清单中的活动设置此主题将起作用:

android:theme="@android:style/Theme.Translucent"

【讨论】:

  • @GauravAgarwal 哎呀。我漏了一步。我编辑了我的答案以显示需要什么。
  • 感谢它现在有效。如何在暂停的活动中绘制箭头并将它们指向正确的坐标?
  • @GauravAgarwal 这真的是一个不同的问题。我建议在暂停内容活动之前,查看每个感兴趣区域的屏幕坐标(对每个感兴趣的视图使用getLocationInWindow)并将这些坐标传递到启动覆盖活动的意图中。您的叠加活动必须使用可以将这些坐标转换为箭头的自定义主视图。
  • 我会尽量按照你说的去做。我认为应该有其他方法来实现这一点。
【解决方案2】:

我刚刚在我的一个项目中实现了 Ted 的答案。伟大的!非常容易实现和漂亮的结果。非常感谢这个 Ted。

但由于 Stack Overflow 用于获取和分享,我想分享我对自定义视图的实现,该视图以“针”的形式创建箭头,我使用 Ted 的方法来完成原始答案。代码如下:

package com.yourpackage;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;
import de.nantoka.miep.R;

public class CoachmarkArrow extends View {

    private static final float CIRCLE_RADIUS = 1.5f;
    private static final int TOPLEFT = 0;
    private static final int TOPRIGHT = 1;
    private static final int BOTTOMLEFT = 2;
    private static final int BOTTOMRIGHT = 3;

    Paint paint;
    int from, to;

    PointF padding = new PointF();
    PointF fromPoint = new PointF();
    PointF toPoint = new PointF();

    public CoachmarkArrow (Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CoachmarkArrow, 0, 0);

        getPaint(a);
        getFromTo(a);

        a.recycle();
    }

    private void getFromTo(TypedArray a) {

        from = a.getInt(R.styleable.CoachmarkArrow_from, BOTTOMLEFT);
        to = a.getInt(R.styleable.CoachmarkArrow_to, TOPLEFT);
    }

    private void getPaint(TypedArray a) {
        paint = new Paint();

        paint.setColor(a.getColor(R.styleable.CoachmarkArrow_color, Color.WHITE));
        paint.setStrokeWidth(a.getDimensionPixelSize(R.styleable.CoachmarkArrow_size, 0));

        paint.setStrokeCap(Paint.Cap.BUTT);
        paint.setAntiAlias(true);
    }

    @Override
    protected void onDraw (Canvas canvas){
        calculatePadding(canvas);
        calculateLinePoints();

        drawLine(canvas, fromPoint, toPoint);
        drawCircle(canvas, fromPoint);
    }

    private void calculateLinePoints() {
        fromPoint = getPoint(from);
        toPoint = getPoint(to);
    }

    private void calculatePadding(Canvas canvas) {

        padding.x = CIRCLE_RADIUS * paint.getStrokeWidth() / canvas.getWidth();
        padding.y = CIRCLE_RADIUS * paint.getStrokeWidth() / canvas.getHeight();
    }

    private PointF getPoint(int position) {
        PointF point = new PointF();

        if (position == TOPRIGHT || position == BOTTOMRIGHT){
            point.x = 1.0f - padding.x;
        }
        else {
            point.x = padding.x;
        }

        if (position == BOTTOMLEFT || position == BOTTOMRIGHT){
            point.y = 1.0f - padding.y;
        }
        else {
            point.y = padding.y;
        }       

        return point;
    }

    private void drawCircle(Canvas canvas, PointF fromPoint) {

        canvas.drawCircle(
                canvas.getWidth() * fromPoint.x, 
                canvas.getHeight() * fromPoint.y, 
                CIRCLE_RADIUS * paint.getStrokeWidth(), 
                paint
                );
    }

    private void drawLine(Canvas canvas, PointF fromPoint, PointF toPoint) {
        canvas.drawLine(
                canvas.getWidth() * fromPoint.x, 
                canvas.getHeight() * fromPoint.y, 
                canvas.getWidth() * toPoint.x, 
                canvas.getHeight() * toPoint.y, 
                paint
                );
    }
}

将此类添加到您的项目中(任何包名都可以)并在 res/values 下为 XML 参数创建一个属性文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CoachmarkArrow">
        <attr name="size" format="dimension" />
        <attr name="color" format="color" />
        <attr name="from" format="enum">
            <enum name="topleft" value="0"/>
            <enum name="topright" value="1"/>
            <enum name="bottomleft" value="2"/>
            <enum name="bottomright" value="3"/>
        </attr>
        <attr name="to" format="enum">
            <enum name="topleft" value="0"/>
            <enum name="topright" value="1"/>
            <enum name="bottomleft" value="2"/>
            <enum name="bottomright" value="3"/>
        </attr>
    </declare-styleable>
</resources>

现在,您可以像任何其他视图一样在 coachmarks 活动的 XML 布局中创建“针”,例如

<com.yourpackage.CoachmarkArrow
    xmlns:coachmark="http://schemas.android.com/apk/res/com.yourproject"    
    android:layout_height="100dp"
    android:layout_width="match_parent"
    coachmark:size="3dip"
    coachmark:color="@android:color/white"
    coachmark:from="bottomright"
    coachmark:to="topleft"
/>  

创建一个“针”,其头部位于右下角,尖端位于矩形的左上角,该矩形高 100 dp,与包含的父 ViewGroup 一样宽。

这样您就可以创建自动适应不同屏幕尺寸的辅助标记。例如,如果您使用相对布局,请为您要在 coachmarks 活动中描述的 UI 元素创建一个虚拟视图,并告诉相对布局将教练标记放在虚拟视图下方但位于您居中的说明文本框上方在窗口的中间。这样,coachmark 会自动获得正确的大小,以从文本框指向 UI 元素。

希望这对某人有所帮助!

【讨论】:

  • 感谢您发布此内容,效果很好。我唯一遇到的麻烦是样式中的 attr name="color",现在说它已经定义了。显然,Android 开发工具发生了一些变化。只需将其更改为“kolor”即可正常工作。
  • @Nantoka - 我是新手,我不知道在哪里添加它以及如何开始。你能帮帮我吗?
  • @Bibhu - 我可以创建一个粗略的步骤草图,但恐怕您必须自己尝试大致了解此解决方案的细节。我们开始吧:1)创建一个具有半透明背景的新活动,如 Ted Hopp 的回答中所述 2)将我的 CoachmarkArrow 类的源代码复制到 src 目录中 3)将 XML 参数复制到 res/values 下的文件中 4 ) 使用 CoarcharkArrow 小部件设计 UI 布局或具有半透明背景的活动,如示例 4) 以意图启动活动,以便它覆盖您为其制作的活动标记
  • @Nantoka - 谢谢,我也做了同样的事情,结果成功了。但我面临的一个问题是找出我想要指向的“按钮/控件”的位置。你能建议怎么做吗?
  • @Bibhu - 我通过“反复试验”来做到这一点,因为编写 UI 元素来替换原始 UI 元素与 coachmarks 会非常复杂。并确保您在具有不同显示尺寸的设备上测试您的设计,以确保箭头准确显示在您想要的位置。
【解决方案3】:

我尝试过做类似的事情。我使用 Activity 制作了消息对话框。对于我在 Manifest 中写的这个活动:

<activity android:name=".MessDial"
 android:label="@string/lblDialog"
 android:theme="@style/Theme.Transparent">
</activity>

在这个活动的主体中,我没有任何特别的透明度。

希望对你有帮助。

【讨论】:

  • 如题中的箭头所示,如何正确显示消息?
  • 我现在不明白你的问题。我看到它就像一个带有一些信息的屏幕,点击这个屏幕它应该关闭。您在此屏幕中输入的所有内容都是另一个问题,与透明度无关。
  • 我的问题还在于说明页面,而不仅仅是透明度。
  • 最简单的方法是制作一张包含所有信息和透明背景的大图像。通过这种方式,您可能需要为每种类型的屏幕制作它,即小、媒体、大。然后让监听器点击这张图片。
  • 请说明您的建议是什么?
【解决方案4】:

您可以尝试使用此示例显示第一次指令屏幕,而无需任何其他库
如果您只想在第一次显示指令,您可以在偏好存储中添加一些标志。一个例子可以找到here

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    SharedPreferences pref= PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    boolean check = pref.getBoolean("firstime", true);
    if(check==true){
        Intent i = new Intent(MainActivity.this, Tutorial_screen.class);//starting activity for the Frist time
        startActivity(i);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 2011-01-11
    相关资源
    最近更新 更多