android 網易云閱讀 書架的實現

 看了網上開源書架的實現以及一些閱讀類軟件的書架,大部份都是書架的高都是固定的豎屏滑動,沒有像網易那樣是3x3 固定的跨平拖動(雖然有zaker跨平拖動代碼,猛的一看複雜多了且效果在閱讀類軟件上面并不是太好),網易云閱讀關鍵是可以在所有的手機上都可以完美的實現,所以很想實現,如下:

  1 自定義個FrameLayout

package org.chinamil.networkerr;
import org.chinamil.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class MyLinearLayout extends FrameLayout {
private Bitmap background,background2 ,background3;
OndsipatchDraw onDraw;
FrameLayout.LayoutParams layoutParams;
public int eage,nogengg;
public interface OndsipatchDraw{
public void MyDraw(int eage);
}
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();

}
public void setOndsipatchDrawListener(OndsipatchDraw draw) {
this.onDraw=draw;
}
private void init() {
background = BitmapFactory.decodeResource(getResources(),
R.drawable.bk);//113 155
background3 = BitmapFactory.decodeResource(getResources(),
R.drawable.bai);//113 155
this.onDraw=onDraw;
}
@Override
protected void dispatchDraw(Canvas canvas) {

int count = getChildCount();
int width = getWidth();
int height = getHeight();// 768 964 3
nogengg= eage=getHeight()/3;//每个书架的高
onDraw.MyDraw(eage);
background2=Tool.resizeBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.bk),width,
eage);//創建適合的背景圖片
int backgroundWidth = background2.getWidth();
int backgroundHeight = background2.getHeight()+0;
for (int y = 0; y < height; y += backgroundHeight) {
for (int x = 0; x < width; x += backgroundWidth) {
canvas.drawBitmap(background2, x, y-5, null);
}
}
background3 = Tool.resizeBitmap(background3,
width,
eage/10);
for (int y = 0; y <=3 ; y ++,eage=eage*y) {
if (y!=0) {
if (y==3)
canvas.drawBitmap(background3, 0, height-background3.getHeight(), null);
else
canvas.drawBitmap(background3, 0,eage-nogengg/10, null);
}
}
/*
int count = getChildCount();
int top = count > 0 ? getChildAt(0).getTop() : 0;
int backgroundWidth = background.getWidth();
int backgroundHeight = background.getHeight()+2;
int width = getWidth();
int height = getHeight();

for (int y = top; y < height; y += backgroundHeight) {
for (int x = 0; x < width; x += backgroundWidth) {
canvas.drawBitmap(background, x, y, null);
}
}
super.dispatchDraw(canvas);*/
super.dispatchDraw(canvas);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}

}

 

這個效果

它無論在多大屏幕的手機上面都會是這個效果 並且都是3行

然後上面覆蓋一個gridview  而至於gridview的item 的寬與高來源就是上面定義的接口 在dispatchDraw 調用的時候會傳遞給使用到它的activity,根據這個數值然後為gridview 創建適合的item圖片資源(需微調一下會有一點誤差但是已經在10個像素內了)。效果如下圖

至於左右拖動 使用的是viewpager 但是為了解決gridview item的拖動 需要重寫viewpager的dispatchTouchEvent方法

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
View v = this.getChildAt(0);
if (v instanceof GridView) {
GridView gridView= (GridView) v;
if ( gridView.getTag().equals("zhuce")) { //用來判斷是否應該滑動  而這個tag是會改變的 
return gridView.dispatchTouchEvent(ev);
} else

return super.dispatchTouchEvent( ev);
}

return false;
//return super.dispatchTouchEvent( ev);
}

在item上面長安進入可拖動狀態

代碼如下 這個是在主activity裏面監聽

inflate.setOnItemLongClickListener(new OnItemLongClickListener( ) {
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
if (parent instanceof GridView) { //缩小grdiiew的item
isTouch=true;
ScaleAnimation animation= new ScaleAnimation(1.0f,0.8f, 1.0f, 0.8f);
animation.setDuration(700);
animation.setFillAfter(true);
for (int j = 0; j < parent.getChildCount(); j++) {
if (j!=position) {
View view2= parent.getChildAt(j);
view2.startAnimation(animation);
}
}
}
int []location=new int[2];
view.getLocationOnScreen(location);
MotionEvent event=MotionEvent.obtain(System.currentTimeMillis(),
System.currentTimeMillis(), MotionEvent.ACTION_DOWN,
location[0], location[1], 0);
onTouch(view, event); //這裡需要我們手動來調用一下 ontouch事件  這個接口由主activity來實現  無論是點擊還是長安都會進入 ontouch方法裏面去
inflate.setOnTouchListener(ErrorBookShelfActivityTouch.this);
inflate.setTag("zhuce");
return true;
}
});

//在item上面點擊的時候

inflate.setOnItemClickListener(new OnItemClickListener() {

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (!isTouch) {
Log.i("xx", "setOnItemClickListener");
}
}
});

 

 

觸摸方法

public boolean onTouch(View v, MotionEvent event) {

lajiImageView.getLocationOnScreen(lajilocation);//這個圖片是一個刪除按鈕 作用在於當 拖動到它上面是就把被拖動的刪除
Log.i("xx", "ljillllllllljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"+lajilocation[0]+"ggggggggg"+lajilocation[1]);
lajiImageView.setVisibility(View.VISIBLE);
//getRawX()和getRawY()获得的是相对屏幕的位置
//getX()相对于控件的本身
GridView mGridView=imageViews.get(viewPager.getCurrentItem());
float x = event.getX();
float y = event.getY();
// 代表当前点击的位置,相对于资源中的位置。产生-1值是超出GridView的范围;
position = mGridView.pointToPosition((int) x, (int) y);
myposition=position;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("xx","ACTION_DOWNlong");
//判断是点击位置是否在GridView中
ACTION_DOWNX=event.getX();
ACTION_DOWNy=event.getY();
if (position == -1) {
break;
}
System.out.println(position+"position");
// getChildAt 获取“当前屏幕”上的第几个View
View tempView = mGridView.getChildAt(position - mGridView.getFirstVisiblePosition());
// 获取缓存 要先打开开关
tempView.setDrawingCacheEnabled(true);
Bitmap tempBitmap = tempView.getDrawingCache();
// 自定义一个图片控件
ImageView imageView = new ImageView(getApplicationContext());
imageView.setImageBitmap(tempBitmap);
// 任何改变控件在界面上的显示状态 只有通过layoutParams
RelativeLayout.LayoutParams rllp = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
//getLeft , getRight 这一组是获取相对在它父亲里的坐标
rllp.leftMargin = tempView.getLeft();
rllp.topMargin = tempView.getTop();
// 代表down的时候点击的坐标 距此图标左上角的偏移量
clickX = (int) (x - tempView.getLeft());
clickY = (int) (y - tempView.getTop());
rl.addView(imageView, rllp);
mDragView = imageView;
// 设置控件不可见
tempView.setVisibility(View.INVISIBLE);
// 保存起点位置
from = position;
break;
// 拖动动作中
case MotionEvent.ACTION_MOVE:
Log.i("xx","ACTION_MOVElong");
if (mDragView == null) {
break;
}
mDragView.getLocationOnScreen(mydraw);
// 从ImageView中获取所有布局参数
RelativeLayout.LayoutParams lp = (LayoutParams) mDragView.getLayoutParams();
//减去偏移量为了让图片能以触摸点为中心显示
lp.leftMargin = (int) x - clickX;
lp.topMargin = (int) y - clickY;//+(backgroundhei-backgroundhei/10)/3
//设置ImageView的布局参数
mDragView.setLayoutParams(lp);
//记住要替换的位置,相对于资源位置中
to = position;
Log.i("xx", mydraw[0]+"movemove"+mydraw[1]);
/* */
// Log.i("xx", event.getX()+"movemove"+event.getY());
//判断交换条件,替换位置要在GridView中,原始位置不等于即将替换位置,动画效果是否结束
/* if (to != -1 && from != to && !doingAni) {
Myarrayadapter madapter=(Myarrayadapter)mGridView.getAdapter();
// 交换位置的代码
PdfDomin temp = madapter.getItem(from);
madapter.remove(temp);
madapter.insert(temp, to);
aniFrom = from;
aniTo = to;
from = to;
}*/
break;
case MotionEvent.ACTION_UP:
isTouch=false;
lajiImageView.setVisibility(View.INVISIBLE);
Log.i("xx","ACTION_UPlllllllllllllllllllllll");
if (mDragView != null) {
//移除自定义的ImageView
rl.removeView(mDragView);
View temp = mGridView.getChildAt(from
- mGridView.getFirstVisiblePosition());
temp.setVisibility(View.VISIBLE);
}

for (GridView element : imageViews) {
if (element.getTag().equals("zhuce")) {
element.setOnTouchListener(null);
element.setTag("no");
for (int i = 0; i <element.getChildCount(); i++) {
element.getChildAt(i).clearAnimation();
}
}
}
if (mydraw[1]<=0) {
if (!isShow) {
ErrorDialog("删除");
isShow=!isShow;
}

}
}
return true;
}

對於item 還需要給他設置移動動畫 在getview方法裏面加入

Animation an = null;
if (position > aniTo && position <= aniFrom) {
if (position % 5 == 0) {
//设置位移动画的参数
an = new TranslateAnimation(255, 0, -85, 0);
} else {
//设置位移动画的参数
an = new TranslateAnimation(-60, 0, 0, 0);
}
} else if (position < aniTo && position >= aniFrom) {
if (position % 5 == 4) {
//设置位移动画的参数
an = new TranslateAnimation(-255, 0, 85, 0);
} else {
//设置位移动画的参数
an = new TranslateAnimation(60, 0, 0, 0);
}
}
if (an != null) {
an.setDuration(300);
// 做动画的时候不能做位置交换
an.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
doingAni = true;
}

public void onAnimationRepeat(Animation animation) {
}

public void onAnimationEnd(Animation animation) {
doingAni = false;
}
});
imageView.setAnimation(an);
}

至此大體上都已經完成 主要的觸摸衝突已經解決 對於每個頁面gridview 的數據 等其他需要實現的都很簡單了

這個至少我現在還沒有運動適配效果不行的,而我沒有還未實現跨平拖動,前段時間分析了下網易云閱讀的佈局他的左右滑動式用gally來實現的比viewpager 要好多了,至少觸摸衝突不需要考慮,若有不對之處還請指出,哪位大神實現跨平拖動還望告知,不勝感激,以上純作個人思考所記錄不做教程也不該,諸君看看就罢了.

 

posted @ 2013-08-14 20:00  z智h慧  阅读(451)  评论(0编辑  收藏  举报