3

在应用程序“Google Play”中,我们可以看到,如果您单击任何项​​目(LinearLayout、按钮、imageview、textview ...),它上面有一件蓝色外套。

上面不是一个简单的背景 android: state_pressed = "true" android: state_focused = "true" ...

知道如何应用这种效果吗?

例如,我有一个带有多个图像和文本的 LinearLayout。这个 LinearLayout 充当“按钮”,我的意图是在外观上按下一个蓝色层,就像谷歌一样。

我通常使用自定义背景,但这适用于而不是结束。

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:state_focused="true" android:drawable="@drawable/focus_blue_default" />
</selector>

focus_blue_default.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#8051C9EC" />
</shape>
</item>
</layer-list>

在此处输入图像描述

4

4 回答 4

3

这仅供参考,我认为它不实用,未经测试,......

既然答案被接受了,我将陈述这段代码的问题(我现在能想到的):

  1. 正如@user2558882 在他对答案的评论中所说,如果子类使用setContentView(view, params)这些参数就会丢失。
  2. 这不适用于膨胀的视图——即适配器;但是,您可以通过调用fix(View)任何膨胀视图来解决。
  3. 它只适用于颜色。这也可以修复。
  4. 我认为这可能适用于sherlock-actionbar。
  5. 代码未测试,请测试。
  6. 它通过添加一个RelativeLayout 将你的整个视图树再移一层。这可以使用addContentView. 我确实使用了这个 RelativeLayout,因为我回答得很快,而且我还认为当前代码在所有手机和 api 上都能更好地工作。这是真的,因为整个解决方案都压缩在一个行为非常一致的 RelativeLayout 中。毕竟我只使用RelativeLayout.LayoutParams了这个 ViewGroup 最基本的功能。

解决方案

创建一个BaseActivity.java

package mobi.sherif.overlay;

import android.app.Activity;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.RelativeLayout;

public class BaseActivity extends Activity {
    RelativeLayout mRl;
    View mImage;
    View mContent;
    @Override
    public void setContentView(int layoutResID) {
        setContentView(LayoutInflater.from(this).inflate(layoutResID, null));
    }
    @Override
    public void setContentView(View view) {
        setContentView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    }
    @Override
    public void setContentView(View view, LayoutParams params) {
        mContent = view;
        fix(view);
        push(view);
    }
    protected void refix() {
        fix(mContent);
    }
    private void push(View view) {
        mRl = new RelativeLayout(this);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
        mRl.addView(view, params);
        mImage = new View(this);
        mImage.setVisibility(View.GONE);
        params = new RelativeLayout.LayoutParams(0, 0);
        mRl.addView(mImage, params);
        super.setContentView(mRl);
    }
    protected void fix(View child) {
        if (child == null)
            return;

        doFix(child);
        if (child instanceof ViewGroup) {
            fix((ViewGroup) child);
        }
    }

    private void fix(ViewGroup parent) {
        for (int i = 0; i < parent.getChildCount(); i++) {
            fix(parent.getChildAt(i));
        }
    }
    private void doFix(View child) {
        if(child.getTag()!=null && child.getTag().getClass() == String.class) {
            String color = (String) child.getTag();
            int theColor;
            try {
                theColor = Color.parseColor(color);
                child.setTag(theColor);
            } catch (Exception e) {
                theColor = -1;
            }
            if(theColor != -1) {
                child.setOnTouchListener(new OnTouchListener() {

                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            mImage.setBackgroundColor((Integer) v.getTag());
                            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mImage.getLayoutParams();
                            params.leftMargin = getLeftWithRespectTo(v, mRl);
                            params.topMargin = getTopWithRespectTo(v, mRl);
                            params.width = v.getWidth();
                            params.height = v.getHeight();
                            mImage.setVisibility(View.VISIBLE);
                            mImage.requestLayout();
                            break;
                        case MotionEvent.ACTION_CANCEL:
                        case MotionEvent.ACTION_UP:
                            mImage.setVisibility(View.GONE);
                        default:
                            break;
                        }
                        return v.onTouchEvent(event);
                    }
                });
            }
        }
    }
    private int getLeftWithRespectTo(View view, View relative) {
        int left = 0;
        View temp = view;
        do {
            left += temp.getLeft();
            temp = (View) temp.getParent();
        }
        while(temp!=relative);
        return left;
    }
    private int getTopWithRespectTo(View view, View relative) {
        int top = 0;
        View temp = view;
        do {
            top += temp.getTop();
            temp = (View) temp.getParent();
        }
        while(temp!=relative);
        return top;
    }
}

现在扩展这个 BaseActivity 和你想要覆盖它的任何视图,使用android:tag="#AARRGGBB"如下颜色:

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tag="#331111ff"
    android:text="@string/hello_world" />

测试:如果你像这样在activity_main.xml中使用xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="17dp"
        android:layout_marginTop="90dp"
        android:tag="#331111ff"
        android:text="TextView" />

</RelativeLayout>

并将其用作您的MainActivity.java

package mobi.sherif.overlay;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class MainActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
        findViewById(R.id.textView1).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "text tpicjed", Toast.LENGTH_SHORT).show();
            }
        });
    }
}
于 2013-09-26T14:23:30.310 回答
1

虽然这可能不是您所要求的,但我确实提出了一种易于重复使用的方法,使控件在按下它们时变为半透明,然后在您停止按下它们时让它们恢复正常显示。

这是代码:

public class ViewTouchHighlighter implements OnTouchListener 
{

    @Override
    public boolean onTouch(View v, MotionEvent event) 
    {
        if (event.getAction() == MotionEvent.ACTION_DOWN)
        {
            AlphaAnimation animation = new AlphaAnimation(1, 0.5f);
            animation.setDuration(0);
            v.startAnimation(animation);

        }
        else
        {
            AlphaAnimation animation = new AlphaAnimation(0.5f, 1);
            animation.setDuration(0);
            v.startAnimation(animation);
        }
        return false;
    }

}

然后,您可以简单地抓取任何视图,并给它这样的行为:

view.setOnTouchListener(new ViewTouchHighlighter());

我意识到这与您正在寻找的有点不同,但是如果您想要突出显示,这可以作为一个很好的解决方案。

如果您坚持使用蓝色效果,和/或您想要在选择时显示为蓝色的东西,而不是在简单触摸时,那么恐怕我会同意@Daniel 并建议您从任何组件继承您可能想要这样做并在那里添加您的自定义代码。

于 2013-09-25T14:55:57.210 回答
1

据我所知,Google play 上使用的容器布局(用于单个项目)是一个相对布局。使用RelativeLayout 实现这个效果相当简单。您已经准备好大部分组件。这是最后一步:

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white" >

    <ImageView 
    ........../>

    <TextView 
    ........../>

    <WhateverView 
    ........../>

    <!--     The final piece -->

    <View
        android:id="@+id/clickableView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:background="@drawable/state_selector_drawable" />

</RelativeLayout>

而且,在您的活动中,您将在此视图中添加一个 OnClickListener:

View clickableView = findViewById(R.id.clickableView);

clickableView.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View arg0) {

        Toast.makeText(MainActivity.this,
                 "Click registered.", Toast.LENGTH_SHORT).show();

    }

});

假设您已经设置了 LinearLayout,并且不希望切换到 RelativeLayout。没关系。将 LinearLayout 及其子项放在 RelativeLayout 中。并添加上面定义的视图:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white" >


        <ImageView 
        ........../>

        <TextView 
        ........../>

        <WhateverView 
        ........../>

    </LinearLayout>

    <!--     The final piece -->

    <View
        android:id="@+id/clickableView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:background="@drawable/state_selector_drawable" />

</RelativeLayout>
于 2013-09-25T20:25:53.637 回答
1

假设您想在 a 上实现此效果Button

  1. 创建一个扩展 Android类的Button
  2. 有一个布尔标志作为类成员,true当您希望此效果出现时将设置为(我想说您可以根据检测到的触摸事件设置它的值onTouchEvent(MotionEvent event)- 只需在您的类中覆盖它并分析这些事件)。
  3. 覆盖方法,并在调用 super 之后,添加一个 if 子句,如果布尔标志为真onDraw(),它将在整个视图上绘制这个彩色矩形(使用)。Paint

几个重要的点:

  • 步骤 3 的替代方法:您可以通过使用(半透明,蓝色)来实现相同的效果,drawable您将根据标志添加或删除它。
  • boolean更改值后,您可能需要使视图无效。
于 2013-09-11T18:07:27.623 回答