看了網上開源書架的實現以及一些閱讀類軟件的書架,大部份都是書架的高都是固定的豎屏滑動,沒有像網易那樣是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 要好多了,至少觸摸衝突不需要考慮,若有不對之處還請指出,哪位大神實現跨平拖動還望告知,不勝感激,以上純作個人思考所記錄不做教程也不該,諸君看看就罢了.