Android项目Tinder学习一

Tinder

登录/注册模块

  • shape实现渐变背景
<!--res/drawable/bg_register.xml 创建shape文件-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
 	android:angle="90" <!--渐变角度:垂直-->
        android:endColor="@color/c1"
        android:startColor="@color/colorAccent"></gradient>
</shape>
<!--res\layout\activity_register.xml 在布局文件中修改背景-->
android:background="@drawable/bg_register"
<!--清单文件 application 修改主题-->
android:theme="@style/Theme.AppCompat.NoActionBar"
  • shape/自定义控件实现圆角UI
//导入包,注意版本号与项目一致
implementation 'com.android.support:design:29.0.0'
implementation "com.android.support:cardview-v7:29.0.0"
<!--头像圆角:设置CardView属性实现圆角-->
	app:cardCornerRadius="@dimen/d10"
<!--输入框圆角:shape背景-->
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@android:color/white" />
    <corners
        android:bottomLeftRadius="25dp"
        android:bottomRightRadius="25dp"
        android:topLeftRadius="25dp"
        android:topRightRadius="25dp"/>
</shape>
<!--按钮圆角背景实现类似-->
//在Activity的onCreate中修改状态栏颜色
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(Color.TRANSPARENT);//状态栏透明
    View view = window.getDecorView();
    view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
  • 选择头像/输入框监听/登录注册业务
//选择头像
private void selectPhoto() {
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
    startActivityForResult(intent, 100);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == 100) {
        if (resultCode == RESULT_OK) {
            Uri data1 = data.getData();
            ivPhoto.setImageURI(data1);
           // getmPersenter().uploadImage(Utils.getDataUrl(this, data1));
        }
    }
}

//输入框监听

public class RegisterActivity implements View.OnClickListener, TextWatcher {

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}

@Override
public void afterTextChanged(Editable editable) {
    name = getEditText(etName);
    email = getEditText(etEmail);
    pass = getEditText(etPass);
    if (name.length() > 0 && email.length() > 0 && pass.length() >= 6) {
        btRegister.setBackgroundResource(R.drawable.bg_btn_register);
    } else {
        btRegister.setBackgroundResource(R.drawable.bg_bt_register_not);
    }

}

}

//跳转
public void startIntnet(Class<?> cls) {
    Intent intent = new Intent();
    intent.setClass(this, cls);
    startActivity(intent);
}
//清单文件中修改启动模式
<activity
    android:name=".ui.user.LoginActivity"
    android:launchMode="singleTask" />
<activity
    android:name=".ui.user.RegisterActivity"
    android:launchMode="singleTask"
    android:windowSoftInputMode="adjustPan|stateHidden" />
  • mvp
//数据父类class BaseModel<T>
public class BaseModel<T> {
    private int code;
    private String message;
    private T data;
    -
    -
    -
    }
    
//interface BaseView<T> 
public interface BaseView<T> {
    void setData(T data,String action);
    void error(String e);
}

//管理者 class BasePersenter<V extends BaseView> 
public class BasePersenter<V extends BaseView> {
    private V mBaseView;

    public void bindView(V view) {
        if (view != null) {
            this.mBaseView = view;
        }
    }

    public void unBindView() {
        mBaseView = null;
    }

    public V getmBaseView() {
        return mBaseView;
    }
}


********
public abstract class BaseActivity<V extends BaseView, P extends BasePersenter>
        extends AppCompatActivity implements BaseView {


    private P mPersenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());
          if (mPersenter == null) {
            mPersenter = createPersenter();
            mPersenter.bindView(this);
        }
        initView();
	initData();
     }

public abstract P createPersenter();

public P getmPersenter() {
    return mPersenter;
}

public abstract int getLayoutId();

public abstract void initView();

public abstract void initData();
}
public class MainActivity extends BaseActivity<MainView, MainPersenter> implements MainView, View.OnClickListener

public class MainModel
public interface MainView extends BaseView 
public class MainPersenter extends BasePersenter<MainView> 
  • 网络请求
//网络请求库
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.7.0'
implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
//网络请求工具类
public class HttpUtils {

    private static OkHttpClient okHttpClient;
    /**
     * 生产环境
     */
    private static final String BASE_URL = "http://101.132.114.122:8099/";
    /**
     * 测试环境
     */
    private static final String BASE_URL_TEST = "http://101.132.114.122:8099/";

    public static String isTest(boolean isTest) {
        if (isTest) {
            return BASE_URL_TEST;
        } else {
            return BASE_URL;
        }
    }

    public static <T> T createApi(Class<T> tClass) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(isTest(true))
                .client(getClient())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(tClass);
    }

    private static synchronized OkHttpClient getClient() {
        if (okHttpClient == null) {
            okHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(true)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .connectTimeout(20, TimeUnit.SECONDS)
                    .addInterceptor(getInterceptor())
                    .build();
        }
        return okHttpClient;
    }

    /**
     * 拦截器
     *
     * @return
     */
    private static Interceptor getInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(
                message -> Log.e("http:=====>", message)
        );
        return interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    }

    public static <T> void sendHttp(Observable<T> observable, final ResponseListenter<T> listenter) {
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<T>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(T t) {
                        if (listenter != null) {
                            listenter.onSccess(t);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("tag", "=========>" + e);
                        if (listenter != null) {
                            listenter.onFail(e.getMessage());
                        }
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}



//监听器
public interface ResponseListenter<T> {
    void onSccess(T data);

    void onFail(String e);
}

//API管理类
public interface ApiService {

    @FormUrlEncoded
    @POST("/user/register")
    Observable<BaseModel<RegisterModel>> getRegister(@Field("user_type") int userType,
                                                     @Field("photo") String photo,
                                                     @Field("name") String name,
                                                     @Field("email") String email,
                                                     @Field("password") String pass);

    @FormUrlEncoded
    @POST("/user/login")
    Observable<BaseModel<LoginModel>> getLogin(@Field("user_type") int userType,
                                               @Field("email") String email,
                                               @Field("password") String pass);
@GET("/user/public_user_list")
Observable<BaseModel<List<MainModel>>> getPublicList(
        @Query("token") String token,
        @Query("page") int page,
        @Query("pageSize") int pageSize);
---
---
---
}

//使用
/**
 * 发起注册
 */
public void sendRegister(String photo, String name, String email, String pass) {
    HttpUtils.sendHttp(HttpUtils.createApi(ApiService.class)
                    .getRegister(1, photo, name, email, pass),
            new ResponseListenter<BaseModel<RegisterModel>>() {
                @Override
                public void onSccess(BaseModel<RegisterModel> data) {
                    if (!Utils.isEmpty(data)) {
                        if (data.getCode() == 200) {
                            RegisterModel model = data.getData();
                            if (getmBaseView() != null) {
                                getmBaseView().setData(model.getToken(), SEND_REGISTER);
                            }
                        }
                    }
                }

                @Override
                public void onFail(String e) {
                    if (getmBaseView() != null) {
                        getmBaseView().error(e);
                    }
                }
            });
}





//Activity:
@Override
public void setData(Object data, String action) {
    if (action.equals(UPLOAD_IMAGE)) {
        photo = (String) data;
        return;
    }
    if (data != null) {
        String token = (String) data;
        SharedPreferencesUtils.saveToken(this, "token", token);
        startIntnet(MainActivity.class, true);
    }
}

@Override
public void error(String e) {
    Log.e("error", "" + e);
}

类似社交app tinder的滑动卡片效果,流畅,体验很好。可以用来实现滑到左边喜欢,右边不喜欢之类的功能,卡片内容的添加是用的Adapter项目地址:https://github.com/wenchaojiang/AndroidSwipeableCardStack 效果图:如何使用创建控件实例<com.wenchao.cardstack.CardStack         android:id="@ id/container"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:padding = "20dp"         android:clipChildren="false"         android:clipToPadding="false"     />mCardStack = (CardStack)findViewById(R.id.container);2. 设置单张卡片的布局文件mCardStack.setContentResource(R.layout.card_content);3.设置AdaptermCardStack.setAdapter(mCardAdapter);一个简单的Adapterpublic class CardsDataAdapter extends ArrayAdapter<String> {     public CardsDataAdapter(Context context, int resource) {         super(context, resource);     }     @Override     public View getView(int position, final View contentView, ViewGroup parent){         TextView v = (TextView)(contentView.findViewById(R.id.content));         v.setText(getItem(position));         return contentView;     } }由于在上面已经设置了单张卡片的布局文件R.layout.card_content,所以在getView()中你不需要在加载并实例化R.layout.card_content,CardStack已经帮你实例化,你只需要使用contentView。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值