代码之家  ›  专栏  ›  技术社区  ›  ephramd

如何在按下任何项目时应用透明度(焦点?)(就像谷歌一样)?

  •  3
  • ephramd  · 技术社区  · 11 年前

    在应用程序“Google Play”中,我们可以看到,如果你点击任何项目(LinearLayout、按钮、图像视图、文本视图…),上面都有一件蓝色的外套。

    以上并不是安卓系统的简单背景:state_presse=“true”安卓系统: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>
    

    焦点_蓝色_默认.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 回复  |  直到 11 年前
        1
  •  3
  •   Sherif elKhatib    11 年前

    这只是参考,我认为它不实用,也没有经过测试。。。

    既然答案被接受了,我将说明此代码的问题(我现在能想到的问题):

    1. 正如@user2558882在他对答案的评论中所说,如果一个子类使用 setContentView(view, params) params丢失了。
    2. 这将不适用于膨胀的视图,即适配器;然而,你可以通过打电话来解决 fix(View) 在任何膨胀的视图上。
    3. 它只适用于颜色。这也是可以解决的。
    4. 我认为这可能适用于夏洛克动作酒吧。
    5. 该代码尚未经过测试,因此请对其进行测试。
    6. 它通过添加RelativeLayout将整个视图树再移动一级。这可以使用 addContentView 。我确实使用了这个RelativeLayout,因为我回答得很快,而且我还认为当前的代码在所有手机和api上都能更好地工作。这是真的,因为整个解决方案是在RelativeLayout中压缩的,其行为非常一致。毕竟我只是在用 RelativeLayout.LayoutParams 这是这个ViewGroup非常基本的功能。

    解决方案

    创建 基本活动.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" />
    

    测试: 如果您在中使用xml activity最小.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>
    

    用这个作为你的 主要活动.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();
                }
            });
        }
    }
    
        2
  •  1
  •   Daniel L.    11 年前

    假设您想在 Button :

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

    以下几点很重要:

    • 步骤3的替代方案:您可以通过使用(半透明,蓝色) drawable 您将根据标志添加或删除。
    • 更改后,您可能需要使您的视图无效 boolean 价值
        3
  •  1
  •   Gil Moshayof    11 年前

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

    这是代码:

    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&建议您从任何可能要使用的组件继承,并在那里添加自定义代码。

        4
  •  1
  •   Vikram    11 年前

    据我所知,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>