问题
I am very much into designing a login screen.
Something like this:
How Do I actually cut the card from the top so as to fill the drawable on top of it? Any help would be of great value.
[Source: https://www.uplabs.com/posts/login-android-app/]
回答1:
A bit update from Ferdous Ahamed's answer. you need to make your image circular.
just add this to your gradle
compile 'de.hdodenhof:circleimageview:2.2.0'
then in your xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f36121">
<RelativeLayout
android:id="@+id/card_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:layout_marginLeft="24dp"
android:layout_marginRight="24dp"
android:layout_centerInParent="true">
<android.support.v7.widget.CardView
android:id="@+id/card_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="#ffffff"
card_view:cardCornerRadius="4dp"
card_view:cardElevation="0dp"
card_view:cardUseCompatPadding="false" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginTop="50dp"
android:padding="24dp">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Login"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Password"
android:inputType="textPassword"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Sign In"
android:background="@android:color/holo_blue_dark"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/profile_image"
android:layout_width="96dp"
android:layout_height="96dp"
android:src="@drawable/profile"
app:civ_border_width="2dp"
app:civ_border_color="#FF000000"/>
</RelativeLayout>
</RelativeLayout>
all you need to do is use same color. in your parent background and in your imageview use same color for border.
app:civ_border_color="#f36121"
OUTPUT
Refer Github link.
回答2:
You can achieve almost similar by following:
- Create a
RelativeLayout
as a container ofCardView
andImageView
- Set
card_view:cardElevation="0dp"
to showImageView
overCardView
- On
ImageView
, set atransparent circle image
for profileIcon
.
FYI, If you want elevation for your CardView
,
set CardView
elevation ascard_view:cardElevation="4dp"
and set ImageView
elevation higher asandroid:elevation="8dp"
to show ImageView
over CardView
.
Here is the fully working code. Try this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#727272">
<RelativeLayout
android:id="@+id/card_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:layout_marginLeft="24dp"
android:layout_marginRight="24dp"
android:layout_centerInParent="true">
<android.support.v7.widget.CardView
android:id="@+id/card_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="#ffffff"
card_view:cardCornerRadius="4dp"
card_view:cardElevation="0dp"
card_view:cardUseCompatPadding="false" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginTop="50dp"
android:padding="24dp">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Login"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Password"
android:inputType="textPassword"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Sign In"
android:background="@android:color/holo_orange_light"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/icon_circular_profile"
android:layout_centerHorizontal="true" />
</RelativeLayout>
</RelativeLayout>
OUTPUT:
ICON: I have used circular profile icon image from this link
Hope this will help~
回答3:
This screen is very complex in terms of what can be done with the current implementation of shapes and shadows on Android. It might actually be impossible to implement correctly using official libraries. You have to solve two problems - how to cut the view and how to provide a shadow for that view.
The support CardView's shadow is created using some kind of a gradient and supports only one case - the rounded rectangle. The Lollipop's shadow can take any shape as long as the shape is convex - which is not your case. As far as I know, there's no 3rd party library which could help you with that. You'd have to make your own shadow using RenderScript blur or just provide a background with a shadow.
It's possible to cut out the circular shape at the top. It requires some custom drawing/masking, but can be done pretty easily using standard Android library. You can do that using Canvas.saveLayer/restore() + PorterDuff.Mode.CLEAR. More or less like this:
Path circle, card;
PorterDuffXfermode xfereMode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
Bitmap avatar;
// make a layer to make cutting shapes possible
int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
// draw the card and its content
canvas.drawPath(card, paint);
super.draw(canvas);
// clear the circular shape
paint.setXfermode(xfereMode);
canvas.drawPath(circle, paint);
// composite
canvas.restoreToCount(saveCount);
paint.setXfermode(null);
// draw the avatar
canvas.drawBitmap(avatar, x, y, paint);
It's not a compplete solution, but I hope you get the idea. To make a shadow, add a black filter, blur it with RenderScript and draw beneath the actual view.
It's a ton of work. Most likely will be very time consuming to implement correctly and very slow to execute. Layer composition and per-pixel operations are very slow even on modern desktop hardware.
来源:https://stackoverflow.com/questions/43117119/create-a-cardview-with-a-semicircle-on-top