如何应用透明度(焦点?)按任何项目(如谷歌那样)?

时间:2013-09-11 17:52:24

标签: android android-layout android-listview android-view android-custom-view

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

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

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

例如,我有一个包含多个图像和文本的LinearLayout。 这个LinearLayout充当了一个“按钮”,我的目的是在外观上改变一个蓝色层,就像Google一样。

我通常使用自定义背景,但这种情况适用但尚未结束。

<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>

enter image description here

4 个答案:

答案 0 :(得分:3)

这仅供参考,我不认为它是实用的,也没有经过测试......

由于接受了答案,我将陈述此代码的问题(我现在能想到的):

  1. 正如@ user2558882在对答案的评论中所述,如果子类使用setContentView(view, params),则参数将丢失。
  2. 这不适用于膨胀的观点-i.e.适配器;但是,您可以通过在任何膨胀的视图上调用fix(View)来解决。
  3. 它只适用于颜色。这也可以修复。
  4. 我认为这可能适用于sherlock-actionbar。
  5. 代码尚未经过测试,请进行测试。
  6. 通过添加RelativeLayout,将整个视图树移动一层。这可以使用addContentView修复。我确实使用了这个RelativeLayout,因为我快速回答了这个问题,并且我认为当前的代码在所有手机和apis上都能更好地运行。这是正确的,因为整个解决方案在RelativeLayout中压缩,其行为非常一致。毕竟我只使用RelativeLayout.LayoutParams这个ViewGroup的基本功能。

  7. <强>解决方案

    创建 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" />
    

    TEST: 如果您在 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();
                }
            });
        }
    }
    

答案 1 :(得分:1)

假设您希望在Button上实现此效果:

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

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

答案 2 :(得分: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&amp;建议您从可能要执行此操作的任何组件继承并在那里添加自定义代码。

答案 3 :(得分:1)

据我所知,Google Play上使用的容器布局(针对个别项目)是RelativeLayout。使用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>