2017-03-15 11:39:13 xiaoyu940601 阅读数 2478
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21114 人正在学习 去看看 李忠义

这篇文章主要介绍了android中使用Activity实现监听手指上下左右滑动,本文使用了Activity的ontouchEvent方法监听手指点击事件,并给出代码实例,需要的朋友可以参考下

用Activity的onTouchEvent方法实现监听手指上下左右滑动
先看一下效果图:
这里写图片描述

大概思路:

应用了Activity的ontouchEvent方法监听手指点击事件,手指滑动的时候会先按下,滑倒另一个地方再抬起,我们就可以根据按下的坐标和抬起的坐标算出用户是往哪一个方向滑动了。
代码:

ackage com.example.testtt;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.Toast;

public class MainActivity extends Activity {
 //手指按下的点为(x1, y1)手指离开屏幕的点为(x2, y2)
 float x1 = 0;
 float x2 = 0;
 float y1 = 0;
 float y2 = 0;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 //继承了Activity的onTouchEvent方法,直接监听点击事件
 if(event.getAction() == MotionEvent.ACTION_DOWN) {
  //当手指按下的时候
  x1 = event.getX();
  y1 = event.getY();
 }
 if(event.getAction() == MotionEvent.ACTION_UP) {
  //当手指离开的时候
  x2 = event.getX();
  y2 = event.getY();
  if(y1 - y2 > 50) {
  Toast.makeText(MainActivity.this, "向上滑", Toast.LENGTH_SHORT).show();
  } else if(y2 - y1 > 50) {
  Toast.makeText(MainActivity.this, "向下滑", Toast.LENGTH_SHORT).show();
  } else if(x1 - x2 > 50) {
  Toast.makeText(MainActivity.this, "向左滑", Toast.LENGTH_SHORT).show();
  } else if(x2 - x1 > 50) {
  Toast.makeText(MainActivity.this, "向右滑", Toast.LENGTH_SHORT).show();
  }
 }
 return super.onTouchEvent(event);
 }


}
2018-01-12 14:47:29 zl18603543572 阅读数 4392
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21114 人正在学习 去看看 李忠义

说明

控件基于UIView封装完成,采用UIPanGestureRecognizer监听自身的触摸事件,以此处理各种滑动动画操作。
内容之间可以循环切换,采用类似tableView加载机制,达到复用效果

效果

这里写图片描述

代码实现

#import <UIKit/UIKit.h>
@class SMSwipeView;

@protocol SMSwipeDelegate <NSObject>

@required
//获取显示数据内容
-(UITableViewCell*)SMSwipeGetView:(SMSwipeView*)swipe withIndex:(int)index;
//获取数据源总量
-(NSInteger)SMSwipeGetTotaleNum:(SMSwipeView*)swipe;
@end

@interface SMSwipeView : UIView

@property(nonatomic,weak)id<SMSwipeDelegate> delegate;

//层叠透明方式显示 默认NO
@property(nonatomic,assign)BOOL isStackCard;
//加载方法
-(void)reloadData;
//根据id获取缓存的cell
-(UITableViewCell*)dequeueReusableUIViewWithIdentifier:(NSString*)identifier;

@end
#import "SMSwipeView.h"

#define degreeTOradians(x) (M_PI * (x)/180)
//childView距离父View左右的距离
const int LEFT_RIGHT_MARGIN=10;
//当前view距离父view的顶部的值
const int TOP_MARGTIN=16;

@interface SMSwipeView()
//已经划动到边界外的一个view
@property(nonatomic,weak)UITableViewCell * viewRemove;
//放当前显示的子View的数组
@property(nonatomic,strong)NSMutableArray * cacheViews;
//view总共的数量
@property(nonatomic,assign)int totalNum;
//当前的下标
@property(nonatomic,assign)int nowIndex;
//触摸开始的坐标
@property(nonatomic,assign)CGPoint pointStart;
//上一次触摸的坐标
@property(nonatomic,assign)CGPoint pointLast;
//最后一次触摸的坐标
@property(nonatomic,assign)CGPoint pointEnd;
//正在显示的cell
@property(nonatomic,weak)UITableViewCell * nowCell;
//下一个cell
@property(nonatomic,weak)UITableViewCell * nextCell;
//第三个cell
@property(nonatomic,weak)UITableViewCell * thirdCell;
//自身的宽度
@property(nonatomic,assign)int w;
//自身的高度
@property(nonatomic,assign)int h;
//是否是第一次执行
@property(nonatomic,assign)BOOL isFirstLayoutSub;

@end

@implementation SMSwipeView

//从xib中加载该类
-(void)awakeFromNib{
    [super awakeFromNib];
    [self initSelf];
}
//直接用方法初始化
-(instancetype)initWithFrame:(CGRect)frame{
    self=[super initWithFrame:frame];
    [self initSelf];
    return self;
}

//进行一些自身的初始化和设置
-(void)initSelf{
    self.clipsToBounds=YES;
    self.cacheViews=[[NSMutableArray alloc]init];
    //手势识别
    UIPanGestureRecognizer * pan=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
    [self addGestureRecognizer:pan];
}

//布局subview的方法
-(void)layoutSubviews{
    if(!self.isFirstLayoutSub){
        self.isFirstLayoutSub=YES;
        self.w=self.bounds.size.width;
        self.h=self.bounds.size.height;
        [self reloadData];
    }
}

//重新加载数据方法,会再首次执行layoutSubviews的时候调用
-(void)reloadData{
    if (!self.delegate||![self.delegate respondsToSelector:@selector(SMSwipeGetView:withIndex:)]||![self.delegate respondsToSelector:@selector(SMSwipeGetTotaleNum:)]) {
        return;
    }
    self.totalNum=(int)[self.delegate SMSwipeGetTotaleNum:self];
    self.viewRemove=nil;
    UITableViewCell * nowCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex];

    UITableViewCell * nextCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex+1<self.totalNum?self.nowIndex+1:0];

    UITableViewCell * thirdCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex+2<self.totalNum?self.nowIndex+2:self.nowIndex+2-self.totalNum];


    if (self.isStackCard) {
        [thirdCell setAlpha:0.3f];
        [nextCell setAlpha:0.5f];
        [nowCell setAlpha:1];
    }

    [thirdCell removeFromSuperview];
    thirdCell.layer.anchorPoint=CGPointMake(1, 1);
    thirdCell.frame=CGRectMake(LEFT_RIGHT_MARGIN*2, 0, self.w-2*2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
    [self addSubview:thirdCell];
    self.thirdCell=thirdCell;

    [nextCell removeFromSuperview];
    nextCell.layer.anchorPoint=CGPointMake(1, 1);
    nextCell.frame=CGRectMake(LEFT_RIGHT_MARGIN, TOP_MARGTIN/2*1, self.w-2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);

    [self addSubview:nextCell];
    self.nextCell=nextCell;

    [nowCell removeFromSuperview];
    nowCell.layer.anchorPoint=CGPointMake(1, 1);
    nowCell.frame=CGRectMake(0, TOP_MARGTIN, self.w, self.h-TOP_MARGTIN);
    [self addSubview:nowCell];
    self.nowCell=nowCell;


}





#pragma mark swipe触摸的相关手势处理
-(void)swipe:(UISwipeGestureRecognizer*)sender{
    NSLog(@"swipe");
}

-(void)pan:(UIPanGestureRecognizer*)sender{
    CGPoint translation = [sender translationInView: self];
    //CGPoint speed=[sender velocityInView:self];//获取速度
    if (sender.state==UIGestureRecognizerStateBegan) {
        //NSLog(@"begin");
        self.pointStart=translation;
        self.pointLast=translation;
    }

    if (sender.state==UIGestureRecognizerStateChanged) {
        //NSLog(@"change");
        //        CGFloat xMove=translation.x-self.pointLast.x;
        //        CGFloat yMove=translation.y-self.pointLast.y;
        //        self.pointLast=translation;
        //
        //        CGPoint center=self.nowCell.center;
        //        self.nowCell.center=CGPointMake(center.x+xMove, center.y+yMove);

        CGFloat xTotalMove=translation.x-self.pointStart.x;
        //        if (xTotalMove<0) {
        //            self.nowCell.transform = CGAffineTransformMakeRotation(degreeTOradians(90*xTotalMove/self.w));
        //            self.nextCell.transform= CGAffineTransformMakeRotation(degreeTOradians(90*xTotalMove/self.w/2));
        //        }else{
        //            self.nowCell.transform = CGAffineTransformMakeRotation(degreeTOradians(0));
        //            self.nextCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
        //        }

    }

    if (sender.state==UIGestureRecognizerStateEnded) {
        //NSLog(@"end");
        CGFloat xTotalMove=translation.x-self.pointStart.x;
        if (xTotalMove<0) {
            [self swipeEnd];
        }else{
            [self swipeGoBack];
        }

    }
    //    NSLog(@"%@%f%@%f",@"x:",speed.x,@"y:",speed.y);
    //NSLog(@"%@%f%@%f",@"x:",translation.x,@"y:",translation.y);
}

/**
 *  @author StoneMover, 16-12-29 14:12:33
 *
 *  @brief 获取为显示的cell,复用机制
 *
 *  @param identifier id标志
 *
 *  @return 返回的cell,如果缓存中没有则返回空
 */
-(UITableViewCell*)dequeueReusableUIViewWithIdentifier:(NSString *)identifier{

    for (UITableViewCell * cell in self.cacheViews) {
        if ([identifier isEqualToString:cell.reuseIdentifier]) {
            [self.cacheViews removeObject:cell];
            return cell;
        }
    }

    return nil;
}

//滑动到下一个界面
-(void)swipeEnd{
    [UIView animateWithDuration:0.3 animations:^{
        self.nextCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
    }];

    //self.nowCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
    CGPoint center=self.nowCell.center;
    [UIView animateWithDuration:0.3 animations:^{
        self.nowCell.center=CGPointMake(center.x-self.w, center.y);
        self.nowCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
        //        [self.nowCell setAlpha:0.0];
    } completion:^(BOOL finished) {
        self.nowIndex++;
        self.nowIndex=self.nowIndex<self.totalNum?self.nowIndex:0;
        if (self.viewRemove&&[self isNeedAddToCache:self.viewRemove]) {
            [self.cacheViews addObject:self.viewRemove];
            [self.viewRemove removeFromSuperview];
        }
        self.viewRemove=self.nowCell;
        //self.viewRemove.layer.anchorPoint=CGPointMake(0, 0);
        //self.viewRemove.transform=CGAffineTransformMakeRotation(degreeTOradians(-35));


        self.nowCell=self.nextCell;
        self.nextCell=self.thirdCell;



        UITableViewCell * thirdCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex+2<self.totalNum?(int)self.nowIndex+2:(int)self.nowIndex+2-(int)self.totalNum];

        [thirdCell removeFromSuperview];

        thirdCell.layer.anchorPoint=CGPointMake(1, 1);
        thirdCell.frame=CGRectMake(LEFT_RIGHT_MARGIN*2, 0, self.w-2*2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
        self.thirdCell=thirdCell;



        if (self.isStackCard) {
            [self.thirdCell setAlpha:0.3f];
            [self.nextCell setAlpha:0.5f];
            [self.nowCell setAlpha:1];
        }

        [self insertSubview:thirdCell belowSubview:self.nextCell];

        [UIView animateWithDuration:0.2 animations:^{
            self.nowCell.frame=CGRectMake(0, TOP_MARGTIN, self.w, self.h-TOP_MARGTIN);
            self.nextCell.frame=CGRectMake(LEFT_RIGHT_MARGIN, TOP_MARGTIN/2*1, self.w-2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
        }];
    }];
}

//滑动到上一个界面
-(void)swipeGoBack{

    if (!self.viewRemove) {
        NSLog(@"!viewRemove");
        return;
    }

    if (self.nowIndex==0) {
        NSLog(@"!viewRemove+index");
        return;
    }

    CGPoint center=self.viewRemove.center;

    self.nowIndex--;

    //    if ([self isNeedAddToCache:self.thirdCell]) {
    //        [self.cacheViews addObject:self.thirdCell];
    //    }
    [self.thirdCell removeFromSuperview];


    self.thirdCell=self.nextCell;
    self.nextCell=self.nowCell;
    self.nowCell=self.viewRemove;

    if (self.nowIndex==0) {
        self.viewRemove=nil;

    }else{
        UITableViewCell * cell=[self.delegate SMSwipeGetView:self withIndex:(int)self.nowIndex-1];
        [cell removeFromSuperview];
        [self insertSubview:cell aboveSubview:self.nowCell];
        cell.layer.anchorPoint=CGPointMake(1, 1);
        cell.frame=self.viewRemove.frame;
        self.viewRemove=cell;
    }

    [UIView animateWithDuration:.5 animations:^{
        self.nowCell.center=CGPointMake(center.x+self.w, center.y);
        self.nowCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
        self.nextCell.frame=CGRectMake(LEFT_RIGHT_MARGIN, TOP_MARGTIN/2*1, self.w-2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
        self.thirdCell.frame=CGRectMake(LEFT_RIGHT_MARGIN*2, 0, self.w-2*2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
    }];
}

//是否需要加入到缓存中去
-(BOOL)isNeedAddToCache:(UITableViewCell*)cell{
    for (UITableViewCell * cellIn in self.cacheViews) {
        if ([cellIn.reuseIdentifier isEqualToString:cell.reuseIdentifier]) {

            return NO;
        }
    }
    return YES;
}

@end

源码下载 点击查看

更多文章 点击查看

2017-07-06 16:43:22 gavin_Zippo 阅读数 1037
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21114 人正在学习 去看看 李忠义

前言

近期项目原因需要一个上下两屏滑动的效果。可以想象成viewpager左右滑动变成上下滑动。本来想用Srcollview实现,但是由于一些原因,比如按键冲突,和listview布局冲突等等,最后决定自己写一个自定义控件。

思路

由于之前实现过SlidingMenu,所以就考虑参考那个模式,左右滑动变成上下滑动就可以。
其实就是两个大小一样的布局,一个显示在屏幕上,另一个隐藏在屏幕外,等到滑动的时候就显示出来。

代码

我这边继承的是ViewGroup 。再重写onLayout方法,放置一个布局占满屏幕,另一个在屏幕外。

public class MySlidingMenu extends ViewGroup {

    private static final String TAG = MySlidingMenu.class.getName();

    private enum Scroll_State {
        Scroll_to_Open, Scroll_to_Close;
    }

    private Scroll_State state;
    private int mMostRecentY;
    private int downY;
    private boolean isOpen = false;

    private View menu;
    private View mainView;

    private Scroller mScroller;

    private OnSlidingMenuListener onSlidingMenuListener;

    public MySlidingMenu(Context context, View main, View menu) {
        super(context);
        setMainView(main);
        setMenu(menu);
        init(context);
    }

    private void init(Context context) {
        mScroller = new Scroller(context);
    }

    @Override
    protected void onLayout(boolean arg0, int l, int t, int r, int b) {
        mainView.layout(l,t,r,b);
        //设置坐标再屏幕下方
        menu.layout(l, menu.getMeasuredHeight(), r, menu.getMeasuredHeight()*2);
    }

    public void setMainView(View view) {
        mainView = view;
        addView(mainView);
    }

    public void setMenu(View view) {
        menu = view;
        addView(menu);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mainView.measure(widthMeasureSpec, heightMeasureSpec);
        menu.measure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mMostRecentY = (int) event.getY();
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                int moveY = (int) event.getY();
                int deltaY = mMostRecentY - moveY;
                // 如果在菜单打开时向上滑动及菜单关闭时向下滑动不会触发Scroll事件
                if ((!isOpen && (downY - moveY) > 0)
                        || (isOpen && (downY - moveY) < 0)) {
                    scrollBy(0, deltaY);
                }
                mMostRecentY = moveY;
                break;
            case MotionEvent.ACTION_UP:
                int upY = (int) event.getY();
                int dy = upY - downY;
                if (!isOpen) {
                // 菜单关闭时向右滑动超过menu三分之一宽度才会打开菜单
                    if (dy < - menu.getMeasuredHeight() / 3) {
                        state = Scroll_State.Scroll_to_Open;
                    } else {
                        state = Scroll_State.Scroll_to_Close;
                    }
                } else {
                // 菜单打开时当按下时的触摸点在menu区域时,只有向左滑动超过menu的三分之一,才会关闭
                    if (dy > menu.getMeasuredHeight() / 3) {
                        state = Scroll_State.Scroll_to_Close;
                    } else {
                        state = Scroll_State.Scroll_to_Open;
                    }
                }
                smoothScrollto();
                break;
            default:
                break;
        }
        return true;
    }

    private void smoothScrollto() {
        int scrolly = getScrollY();
        switch (state) {
            case Scroll_to_Close:
                mScroller.startScroll(0, scrolly, 0, - scrolly, 500);
                isOpen = false;
                break;
            case Scroll_to_Open:
                mScroller.startScroll(0, scrolly, 0, menu.getMeasuredHeight()- scrolly, 500);
                isOpen = true;
                break;
            default:
                break;
        }
        //需要主动出发一次invalidate,之后再移动的时候自动走computeScroll方法
        invalidate();
    }

    @Override
    public void computeScroll() {
        //滑动时候computeScrollOffset会一直返回false,只有在startScroll结束时候才会为true
        if (mScroller.computeScrollOffset()) {
            scrollTo(0, mScroller.getCurrY());
            postInvalidate();
        }
        super.computeScroll();
    }
}

整段代码不算复杂,最主要的是坐标的计算。startScroll(int startX, int startY, int dx, int dy, int duration)这个方法对于坐标滑动比较难算。开始我一直在纠结dx,dy正的往什么方向,负的往什么方向。后来看了一下源码。

public void startScroll(int startX, int startY, int dx, int dy, int duration) {  
    mMode = SCROLL_MODE;  
    mFinished = false;  
    mDuration = duration;  
    mStartTime = AnimationUtils.currentAnimationTimeMillis();  
    mStartX = startX;  
    mStartY = startY;  //开始滑动坐标
    mFinalX = startX + dx;  
    mFinalY = startY + dy;  //滑动终点坐标
    mDeltaX = dx;  
    mDeltaY = dy;  
    mDurationReciprocal = 1.0f / (float) mDuration;  
    // This controls the viscous fluid effect (how much of it)  
    mViscousFluidScale = 8.0f;  
    // must be set to 1.0 (used in viscousFluid())  
    mViscousFluidNormalize = 1.0f;  
    mViscousFluidNormalize = 1.0f / viscousFluid(1.0f);  
}  

所以如果从A(a1, a2)滑动到B(b1,b2), 只需要startScroll(a1,a2,b1-a1,b2-a2)就行。主要就求个差值。

使用方法

    private MySlidingMenu mSlidingMenu;
    ......
    mSlidingMenu = new MySlidingMenu(this, LayoutInflater
         .from(this).inflate(R.layout.fragment1, null), LayoutInflater
         .from(this).inflate(R.layout.fragment2, null));

补充

这个会导致listview 滑动冲突,如果列数固定可以一屏显示直接重写listviewe的onTouchEvent 返回false就行。如果比较多的话,那就通过在onTouchEvent () 中getParent().requestDisallowInterceptTouchEvent(bool)来设置哪个控件响应事件。

一般的思路是list滑动到头和尾的时候,才将相应方向的滑动事件传给父组件。

2017-06-10 16:49:39 qq_21276791 阅读数 4310
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21114 人正在学习 去看看 李忠义

现在来介绍两种控件RecyclerView和CardView,并通过实例将它们结合在一起实现一种横向卡片式滑动效果.

1.RecyclerView

RecyvlerView是android SDK 新增加的一种控件,也被官方推荐代替ListView来使用,因为其具有更好的灵活性和代替性。

2.CardView

CardView是安卓5.0推出的一种卡片式控件,内部封装了许多有用的方法来实现美观效果。

3.如何使用RecylerView和CardView在android studio中

在build.gradle中添加依赖再编辑即可

compile 'com.android.support:recyclerview-v7:25.+'
compile 'com.android.support:cardview-v7:25

4.通过实例,使用两种控件实现横向卡片式滑动效果

建立main.xml布局文件,代码如下:

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






    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler_View"
        >

    </android.support.v7.widget.RecyclerView>

</LinearLayout>

使用过ListView的同学应该知道还需要一个子布局来填充RecyclerView
以下为recyclerView_item.xml的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                    xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:id="@+id/recyclerview_item"
              android:padding="30dp"

    >

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:contentPadding="50dp"
        app:cardCornerRadius="20dp"
        android:clickable="true"

        android:foreground="?android:attr/selectableItemBackground"
        app:cardElevation="@dimen/cardview_compat_inset_shadow"
        app:cardBackgroundColor="@color/cardview_light_background">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/tv1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="作者"
                android:textSize="22dp"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="114dp"
            >
            <TextView
                android:id="@+id/tv2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="
                锄禾日当午,汗滴禾下土"

                android:textSize="22dp"/>
        </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

从代码中,我们会发现使用了CardView控件以及在控件中添加简易的两个TextView

现在来介绍CardView的一些常用属性,这也是现在卡片效果的关键所在

card_view:contentPadding 这个可以给你的内容加上padding属性
card_view:cardBackgroundColor这个可以改变cardview的背景
card_view:cardCornerRadius这个可以改变cardview圆角的大小
card_view:cardElevation这个比较难解释,CardView的Z轴阴影,被用来决定阴影的大小以及柔和度,以至于可以逼真的模拟出对于深度效果的描述。说白点可以理解为阴影的大小
andorid:foreground=”?android:attr/selectableItemBackground” 这个可以使CardView被点击后出现波纹效

通过以上常用属性可以使CardView出现各种不同的效果

现在回到Activity中来实现RecyclerView

跟ListView的一样,我们需要写一个适配器,代码如下:

public class recyclerViewadapter extends RecyclerView.Adapter {
    private List<DataBean> lists;
    private Context context;

    public recyclerViewadapter(List<DataBean> lists, Context context) {
        this.lists = lists;
        this.context = context;
    }

    class myholder extends RecyclerView.ViewHolder{

        private TextView tv1,tv2;
        public myholder(View itemView) {
            super(itemView);
            tv1= (TextView) itemView.findViewById(R.id.tv1);
            tv2= (TextView) itemView.findViewById(R.id.tv2);


        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        myholder holder =new myholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item,parent,false));
        return holder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        Log.d("TAG", "onBindViewHolder: "+lists.get(position).getAutor());
        ((myholder)holder).tv1.setText(lists.get(position).getAutor());
        ((myholder)holder).tv2.setText(lists.get(position).getContent());

    }

    @Override
    public int getItemCount() {
        return lists.size();
    }
}

写一个类继承RecyclerView.Adapter,重写RecyclerView.Adapter的三个重要方法 onBindViewHolder() getItemCount() 和 OncreateViewHolder()

      OncreateViewHolder(): 创建新的View,被LayoutManager所调用
      OnBindViewHolder():将数据与界面进行绑定
      getItemCount() :返回数据的数量

在Activity中,代码如下:

public class Frament1 extends android.support.v4.app.Fragment{

    private Toolbar toolbar1;
    private RecyclerView recycler_view;
    private TextView tv1,tv2;
    private View view;
    private List<DataBean> lists;


    @Override
    public void onAttach(Context context) {

        super.onAttach(context);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        setHasOptionsMenu(true);
         view = inflater.inflate(R.layout.fragment1, container, false);

        initView();
        initData();
        LinearLayoutManager m=new LinearLayoutManager(getContext());
        m.setOrientation(LinearLayoutManager.HORIZONTAL);
        recycler_view.setLayoutManager(m);
        recyclerViewadapter adapter=new recyclerViewadapter(lists,getContext());
        recycler_view.setAdapter(adapter);



        return view;
    }

    @Override
    public void onResume() {
        super.onResume();

    }

    private void initData() {
        lists=new ArrayList<>();
        lists.add(new DataBean("Smart","青青原上草,一岁一枯荣"));
        lists.add(new DataBean("Smart","青青原上草,一岁一枯荣"));
        lists.add(new DataBean("Smart","青青原上草,一岁一枯荣"));
        lists.add(new DataBean("Smart","青青原上草,一岁一枯荣"));
        lists.add(new DataBean("Smart","青青原上草,一岁一枯荣"));
        lists.add(new DataBean("Smart","青青原上草,一岁一枯荣"));

    }

    private void initView() {
        recycler_view= (RecyclerView) view.findViewById(R.id.recycler_View);
        tv1= (TextView) view.findViewById(R.id.tv1);
        tv2= (TextView) view.findViewById(R.id.tv2);


    }
}

在代码中,我们获取LayoutManager对象,设置其方向为水平方向,并设置RecyclerView的LayoutManager

然后实例化adapter对象,传入上下文和假数据lists,并设置RecyclerView.adapater

 LinearLayoutManager m=new LinearLayoutManager(getContext());
        m.setOrientation(LinearLayoutManager.HORIZONTAL);
        recycler_view.setLayoutManager(m);
        recyclerViewadapter adapter=new recyclerViewadapter(lists,getContext());
        recycler_view.setAdapter(adapter);

到此基本步骤已经完成,运行程序。
以下为运行截图:

这里写图片描述

**这里写图片描述**

作者:乐观的Smart

2015-10-10 20:55:40 weilexuexia 阅读数 724
  • Android开源项目实践之UI篇

    本课程主要展现了如何利用Android开源代码进行app的开发。例如: 1.异步网络请求(android-async-http); 2.百变圆形滚动条(ProgressWheel);3.滑动导航栏(PagerSlidingTabStrip);4.瀑布流与上拉刷新,下拉加载完美结合(PinterestLikeAdapterView)...

    21114 人正在学习 去看看 李忠义

1、初始化ViewFlipper组件


2、push_up_out.xml布局文件


3、push_up_in.xml布局文件


4、main.xml的布局文件


这样就能实现文本上下滑动的效果了。

没有更多推荐了,返回首页