程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 安卓開發之Kotlin和java雙實現仿qq空間下拉圖片拉伸

安卓開發之Kotlin和java雙實現仿qq空間下拉圖片拉伸

編輯:JAVA綜合教程

安卓開發之Kotlin和java雙實現仿qq空間下拉圖片拉伸


先不扯淡看今天要實現的效果:
這裡寫圖片描述
話說使用Kotlin實現安卓功能,那我們還是要做一點准備工作,so,你得加一點插件到eclipse或android studio。然並卵,你現在還在使用eclipse開發的話我只能提供地址Kotlin Plugin for Eclipse,然後我使用的還是死丟丟

死丟丟(android studio)集成kotlin安卓開發

要使用android studio開發kotlin的安卓app,那麼你必須有開發kotlin的環境:

Kotlin插件。打開Android Studio的首選項的搜索插件面板,使用搜索功能查詢Kotlin插件,安裝完成並重啟即可。

這裡寫圖片描述

但是你要使用Kotlin開發安卓程序的話還需要Kotlin Extension For Android,方法也是一樣的

在插件列表中選擇或者搜索Kotlin Extensions For Android並點擊右邊窗口的Install Plugin按鈕:

這裡寫圖片描述

 

給你提個tip:如果你覺得在android studio裡面install 這兩個插件很慢,動不動失敗的話,那麼這裡給你提供一離線地址:(kotlin和kotlin for android),其實家裡網速不好我就是離線下載這麼干的,在公司呢就是在線弄的,以後一般的插件你都可以往這裡面去離線下載。

這裡寫圖片描述


這裡寫圖片描述

是不是基本的插件裝完了就可以開發了,個人推薦你可以再加一個:
Anko 插件
看圖:
這裡寫圖片描述
離線下載:

這裡寫圖片描述

使用方法呢,看下圖:
1. 把.java文件轉成.kt文件:
這裡寫圖片描述
當然你也可以按住 Ctrl+alt+shift+K的組合鍵來使用。
2. 把java的安卓項目變成Kotlin項目:
這裡寫圖片描述
這裡寫圖片描述
3. 新建kotlin文件
這裡寫圖片描述
再來注意下gradle文件:

apply plugin: ‘kotlin-android’
apply plugin: ‘kotlin-android-extensions’

sourceSets {
main.java.srcDirs += ‘src/main/kotlin’
}

dependencies {
compile fileTree(dir: ‘libs’, include: [‘*.jar’])
compile “org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version”
}

buildscript {
ext.kotlin_version = ‘1.0.1-2’
repositories {
mavenCentral()
}
dependencies {
classpath “org.jetbrains.kotlin:kotlin-gradle- plugin:$kotlin_version”
}
}
repositories {
mavenCentral()
}

思路

其實PullToZoomListView的實現原理很簡單:就是一個listView加header,然後header是把圖片作為填充內容,通過滾動和觸摸事件來改變圖片的大小,主要是在case MotionEvent.ACTION_MOVE:代碼段中判斷向下滑動的偏移量,根據這個來改變listview headerView內容區域的高度,並且在手指放開的那一刻,停止縮放,啟用一個動畫來使HeaderView平滑的恢復到放大之前的狀態。

java實現仿qq空間下拉圖片拉伸

我們先來看PullToZoomListView的實現:

package com.example.pulltozoomlistview.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import com.example.pulltozoomlistview.R;
public class PullToZoomListView extends ListView {
    private ImageView mImageView;
    // 初始高度
    private int mImageViewHeight = -1;
    // 最大拉伸高度
    private int mDrawableMaxHeight = -1;
    public PullToZoomListView(Context context,       AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 設置拉伸的圖片
     * 
     * @param imageView
     */
    public void setPullToZoomImageView(ImageView imageView) {
        this.mImageView = imageView;
        // 設置伸縮類型 -- 居中填充
    this.mImageView.setScaleType(ScaleType.CENTER_CROP);
    }

    /**
     * 初始化圖片加載進來最初的高度
     * 
     */
    public void setViewBounds() {
        if (mImageViewHeight == -1) {
            mImageViewHeight = mImageView.getHeight();
            if (mImageViewHeight < 0) {
                mImageViewHeight =  getContext().getResources()
            .getDimensionPixelSize(R.dimen.size_default);
            }
        }
    }

    /**
     * 滑動過頭的時候回調
     */
    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,int scrollY, int scrollRangeX, int scrollRangeY,int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        // 控制ImageView的高度不斷增加
        boolean isCollapse = resizeOverScrollBy(deltaY);
        // return true:下拉到邊界的某個地方的時候不再往下拉
        return isCollapse ? true : super.overScrollBy(deltaX, deltaY, scrollX,scrollY, scrollRangeX, scrollRangeY, maxOverScrollX,maxOverScrollY, isTouchEvent);
    }

    /**
     *  監聽ListView滑動
     */
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        // 獲得ImageView的父控件
        View header = (View) mImageView.getParent();
        if (header.getTop() < 0 && mImageView.getHeight() > mImageViewHeight) {
            // 減小ImageView的高度 -- 不能超過圖片最原始的高度
            mImageView.getLayoutParams().height = Math.max(
                    mImageView.getHeight() + header.getTop(), mImageViewHeight);
            // ImageView所在的容器的高度也要變化:getTop--->0
            header.layout(header.getLeft(), 0, header.getRight(),
                    header.getHeight());
            mImageView.requestLayout();
        }

    }
    private boolean resizeOverScrollBy(int deltaY) {
        // 下拉的過程當中,不斷地控制ImageView的高度
        /**
         * deltaY:是在超出滑動的時候每毫秒滑動的距離 -- 增量 (-往下拉過渡,+往上拉過渡) 大小:根據用戶滑動的速度決定 一般滑動的速度
         * -50~50
         */
        if (deltaY < 0) {
            // 下拉過渡,不斷增加ImageView的高度,deltay是負數,增加高度就是減去
            mImageView.getLayoutParams().height = mImageView.getHeight()
                    - deltaY;
            // View重新調整寬高
            mImageView.requestLayout(); // onMeasure-->onLayout
        } else {
            // 上拉過渡,不斷減小ImageView的高度,deltay是正數,減小高度還是減去
            if (mImageView.getHeight()>mImageViewHeight) {
                mImageView.getLayoutParams().height = Math.max(mImageView.getHeight() - deltaY, mImageViewHeight);
                // View重新調整寬高
                mImageView.requestLayout(); // onMeasure-->onLayout
            }
        }
        return false;
    }
    /**
     * 監聽觸摸 -- 松開手
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        // 判斷
        if (ev.getAction()== MotionEvent.ACTION_UP) {
            // 開啟回彈的動畫
            ResetAnimation animation=new ResetAnimation(mImageView,mImageViewHeight);
            animation.setDuration(300);
            mImageView.startAnimation(animation);
        }
        return super.onTouchEvent(ev);
    }
    public class ResetAnimation extends Animation{
        private ImageView mView;
        private int targetHeight;
        // 動畫執行前的高度
        private int originalHeight;
        // 高度差
        private int extraHeight;
        public ResetAnimation(ImageView mImageView,int targetHeight) {
            this.mView=mImageView;
            this.targetHeight=targetHeight;
            this.originalHeight=mImageView.getHeight();
            extraHeight=originalHeight-targetHeight;
        }
        /**
         * 動畫不斷地執行的時候會回調該方法
         * interpolatedTime:范圍是0
         * 0ms-------------->300ms
         * 當前的圖片高度--->動畫執行之前的高度-高度差*interpolatedTime
         * extraHeight------>0
         */
        @Override
        protected void applyTransformation(float interpolatedTime,Transformation t) {
            mView.getLayoutParams().height=(int) (originalHeight-extraHeight*interpolatedTime);
            mView.requestLayout();
            super.applyTransformation(interpolatedTime, t);
        }
    }

}

MainActivity的簡單使用PullToZoomListView

package com.example.pulltozoomlistview;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import com.example.pulltozoomlistview.view.PullToZoomListView;
public class MainActivity extends AppCompatActivity {
    private PullToZoomListView lv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getSupportActionBar().hide();
        if(Build.VERSION.SDK_INT>=21){
            getSupportActionBar().setElevation(0f);
        }
        lv=(PullToZoomListView) findViewById(R.id.main_lv);
        View header=View.inflate(this, R.layout.layout_lv_header, null);
        lv.addHeaderView(header);
        ArrayAdapter adapter=new ArrayAdapter(this,
                android.R.layout.simple_list_item_1,
                new String[]{"騰訊","阿裡巴巴","百度","新浪","c語言","java","php","FaceBook","Twiter","xml","html"});
        lv.setAdapter(adapter);
        ImageView iv=(ImageView) header.findViewById(R.id.header_img);
        lv.setPullToZoomImageView(iv);
    }

    // 當界面顯示出來的時候回調
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            lv.setViewBounds();
        }
    }
}

Kotlin實現仿qq空間下拉圖片拉伸

同樣我們先來看使用kotlin語言來實現PullToZoomListView:

package com.example.pulltozoom.view
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.animation.Animation
import android.view.animation.Transformation
import android.widget.ImageView
import android.widget.ImageView.ScaleType
import android.widget.ListView
import com.example.pulltozoom.R
open class PullToZoomListView(context: Context, attrs: AttributeSet) : ListView(context, attrs) {
    private var mImageView: ImageView? = null
    // 初始高度
    private var mImageViewHeight = -1
    // 最大拉伸高度
    private val mDrawableMaxHeight = -1
    /**
     * 設置拉伸的圖片
     * @param imageView
     */
    fun setPullToZoomImageView(imageView: ImageView) {
        this.mImageView = imageView
        // 設置伸縮類型 -- 居中填充
        this.mImageView!!.scaleType = ScaleType.CENTER_CROP
    }

    /**
     * 初始化圖片加載進來最初的高度

     */
    fun setViewBounds() {
        if (mImageViewHeight == -1) {
            mImageViewHeight = mImageView!!.height
            if (mImageViewHeight < 0) {
                mImageViewHeight = context.resources.getDimensionPixelSize(R.dimen.size_default)
            }
        }
    }

    /**
     * 滑動過頭的時候回調
     */
    override fun overScrollBy(deltaX: Int, deltaY: Int, scrollX: Int,scrollY: Int, scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int, isTouchEvent: Boolean): Boolean {
        // 控制ImageView的高度不斷增加
        val isCollapse = resizeOverScrollBy(deltaY)
        // return true:下拉到邊界的某個地方的時候不再往下拉
        return if (isCollapse)
            true
        else
            super.overScrollBy(deltaX, deltaY, scrollX,
                    scrollY, scrollRangeX, scrollRangeY, maxOverScrollX,
                    maxOverScrollY, isTouchEvent)
    }
    /**
     * 監聽ListView滑動
     */
    override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
        super.onScrollChanged(l, t, oldl, oldt)
        // 獲得ImageView的父控件
        val header = mImageView!!.parent as View
        if (header.top < 0 && mImageView!!.height > mImageViewHeight) {
            // 減小ImageView的高度 -- 不能超過圖片最原始的高度
            mImageView!!.layoutParams.height = Math.max(
                    mImageView!!.height + header.top, mImageViewHeight)
            // ImageView所在的容器的高度也要變化:getTop--->0
            header.layout(header.left, 0, header.right,
                    header.height)
            mImageView!!.requestLayout()
        }
    }
    private fun resizeOverScrollBy(deltaY: Int): Boolean {
        // 下拉的過程當中,不斷地控制ImageView的高度
        /**
         * deltaY:是在超出滑動的時候每毫秒滑動的距離 -- 增量 (-往下拉過渡,+往上拉過渡) 大小:根據用戶滑動的速度決定 一般滑動的速度
         * -50~50
         */
        if (deltaY < 0) {
            // 下拉過渡,不斷增加ImageView的高度,deltay是負數,增加高度就是減去
            mImageView!!.layoutParams.height = mImageView!!.height - deltaY
            // View重新調整寬高
            mImageView!!.requestLayout() // onMeasure-->onLayout
        } else {
            // 上拉過渡,不斷減小ImageView的高度,deltay是正數,減小高度還是減去
            if (mImageView!!.height > mImageViewHeight) {
                mImageView!!.layoutParams.height = Math.max(mImageView!!.height - deltaY, mImageViewHeight)
                // View重新調整寬高
                mImageView!!.requestLayout() // onMeasure-->onLayout
            }
        }
        return false
    }

    /**
     * 監聽觸摸 -- 松開手
     */
    override fun onTouchEvent(ev: MotionEvent): Boolean {
        // 判斷
        if (ev.action == MotionEvent.ACTION_UP) {
            // 開啟回彈的動畫
            val animation = ResetAnimation(mImageView!!, mImageViewHeight)
            animation.duration = 300
            mImageView!!.startAnimation(animation)
        }
        return super.onTouchEvent(ev)
    }

    inner class ResetAnimation(private val mView: ImageView, private val targetHeight: Int) : Animation() {
        // 動畫執行前的高度
        private val originalHeight: Int
        // 高度差
        private val extraHeight: Int

        init {
            this.originalHeight = mView.height
            extraHeight = originalHeight - targetHeight
        }
        /**
         * 動畫不斷地執行的時候會回調該方法
         * interpolatedTime:范圍是0
         * 0ms-------------->300ms
         * 當前的圖片高度--->動畫執行之前的高度-高度差      *interpolatedTime
         * extraHeight------>0
         */
        override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
            mView.layoutParams.height = (originalHeight - extraHeight * interpolatedTime).toInt()
            mView.requestLayout()
            super.applyTransformation(interpolatedTime, t)
        }
    }
}

接下來使用kotlin實現MainActivity:

package com.example.pulltozoom
import android.os.Build
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.widget.ArrayAdapter
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.layout_lv_header.*
/**
 * QQ空間之打造個性化可拉伸頭部控件
 */
open class MainActivity : AppCompatActivity() {
   // private var lv: PullToZoomListView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        supportActionBar!!.hide()
        //以下代碼用於去除陰影
        if(Build.VERSION.SDK_INT>=21){
            supportActionBar!!.elevation=0f
        }
     //   lv = findViewById(R.id.main_lv) as PullToZoomListView?
        val header = View.inflate(this, R.layout.layout_lv_header, null)
        main_lv!!.addHeaderView(header)
        val adapter = ArrayAdapter(this,
                android.R.layout.simple_list_item_1,
                arrayOf("騰訊","阿裡巴巴","百度","新浪","c語言","java","php","FaceBook","Twiter","xml","html"))
       main_lv!!.adapter = adapter
        //val iv = header.findViewById(R.id.header_img) as ImageView
        main_lv!!.setPullToZoomImageView(header_img)
    }
    // 當界面顯示出來的時候回調
    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        if (hasFocus) {
            main_lv!!.setViewBounds()
        }
    }
}

kotlin Extensions使用總結:

Using Kotlin Android Extensions要點:
1. apply plugin: ‘kotlin-android-extensions’
2. activity_main綁定xml在activity裡這樣寫:
import kotlinx.android.synthetic.main.activity_main.view.*
3. xml裡面的控件不再需要findViewById(),直接用id代替空間來操作

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved